由于没有学过操作系统。所以给这 process,thread,AsyncTask 三个搞糊涂了。。所以给这 process,thread,AsyncTask 三个搞糊涂了。
process 老师没讲过,thread 和 AsyncTask 只是讲了下使用。至于为什么要用 AsyncTask 也没多解释。
今天看了下Processes and Thread,安卓的官方 API Guides. 顺便练练英文。
process
进程。一般来说,一个应用它的每一部分都是在同一个进程里面进行,但,我们可以去改变它。
通过改变 manifest 的 android:process。
而当系统的内存不够用的时候,android 系统会去杀掉一些进程,而杀死的对象也是有优先顺序的。例
如这样:
Foreground process 通常这个进程正在与用户在进行交互。只要满足下面这几点的其中一个点都算是 foreground process
这个 Activity 正在与用户在进行交互(Activity 的 onResume 方法已经被调用)
这个进程里面 Service 绑定了的 activity 正在与用户在进行交互
这个 Service 正在运行在前台,startForeground() 方法被调用
这个 service 的这些回调函数的其中之一被调用(onCreate(), onStart(), or onDestroy())
BroadcastReceiver 的 onReceive() 被调用。
Visible process 这个进程没有一部分是在最前面的,但是它会影响到用户的屏幕显示的内容,它通常满足一下的其中一个点:
它所在的 activity 不是在最前面,但对于用户来说还是可见的(它的 onPause() 方法被调用),就会出现这个情况,例如:一个在最前面的 activity 打开了一个 dialog,这个时候,刚才的 activity 就会在 dialog 后面,自然就被挡住了。
进程的 service 绑定了一个 Visible Activity。
Service process 该进程所运行的 service 调用了 startService() 方法,但又没满足以上两种情况的要求,即使该服务没有直接影响用户所看到的屏幕,但是它还是正在做用户关心的事情,例如,音乐播放器或者是正在下载数据。
Background process 该进程的 activity 没有直接给用户可见(通常 onStop() 方法被调用),该进程也没有直接影响用户所关心的事情,当系统资源不够用的时候,系统会随时把它杀掉,当然,通常会有好多这样的进程存在,这类进程也是有优先等级的,他们的排列方式是以用户使用该应用的最近时间排列。
Empty process 空进程。不解释
Thresds
当应用启动的时候,系统会自动创建一个线程给这个应用,这个线程叫主线程,也成为 UI 线程,因为这个主线程通常只是用来做 UI 的显示,和调用 onCreat(),onStop() 等方法。
做一些简单的事情。
如果需要做一些需要长一点时间或者复杂一些的事情,主线程会阻塞,主线程阻塞了 5 秒会引发”application not responding” (ANR) dialog 的出现,严重影响用户体验。
这个时候我们就需要自行创建工人线程来解决这个问题。
但我们还得遵守两个原则:
不让主线程阻塞。
不在主线程(UI 线程)外的线程进行 UI 的创建和修改。
Worker threads
例子:
1 2 3 4 5 6 7 8 | public void onClick(View v) { new Thread(new Runnable() { public void run() { Bitmap b = loadImageFromNetwork("http://example.com/image.png"); mImageView.setImageBitmap(b); } }).start(); } |
这样做好像已经满足了我们所想的意思了,但其实不是这样,刚说了,我们不在主线程之外的线程作创建或者修改 UI 的动作。这里已经违反了。
安卓提供了几个在其他线程去求该 UI 的方法给我们,如下:
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
例子:1 2 3 4 5 6 7 8 9 10 11 12
public void onClick(View v) { new Thread(new Runnable() { public void run() { final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png"); mImageView.post(new Runnable() { public void run() { mImageView.setImageBitmap(bitmap); } }); } }).start(); }
这个时候,访问网络不再主线程进行了,修改 UI 也脱离主线程,好像真的满足我们的需求了。其实。还是没有达到。
AsyncTask
如果我们都是这样做的话,线程会很多,很多的话就很难去管理,我们可能需要用 Handler 去管理我们的工人线程,在主线程传递信息过去 Handler 去处理。或者,还有一个更好的解决方法,就是使用 AsyncTask 类,它简单化地解决了我们刚才遇到的问题,可以使用到工人线程又可以和 UI 交互。
继承 AsyncTask 类后实现 doInBackground() 回调方法,这个方法将会运行在后台线程(工人线程也称后台线程),要更新 UI 层,我们需要实现 onPostExecute() 方法,这个方法里面的结果是 doInBackground() 传递过来的,这样我们就可以安全更新 UI。我们只需在主线程调用 execute() 方法即可使用 AsyncTask。
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public void onClick(View v) { new DownloadImageTask().execute("http://example.com/image.png"); }private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { /** The system calls this to perform work in a worker thread and * delivers it the parameters given to AsyncTask.execute() */ protected Bitmap doInBackground(String... urls) { return loadImageFromNetwork(urls[0]); } /** The system calls this to perform work in the UI thread and delivers * the result from doInBackground() */ protected void onPostExecute(Bitmap result) { mImageView.setImageBitmap(result); } } |
我们还可以在 AsyncTask 设置进度条,随时可以在 doInBackground() 调用 publishProgress() ,然后用 onProgressUpdate() 更新进度条的 UI 显示。
这里经常会遇到一个问题就是,当我们使用工人线程的时候会出现 runtime configuration change 的错误,例如用户使屏幕横竖颠倒可能会 destroy 我们的工人线程,这里还需要更深入地研究。可见 Shelves 的使用。
还有一点就是,AsyncTask 不适合处理时间过长的任务,只适合处理较短时间的任务,例如几秒钟,如果要处理长时间的任务的话,android 提供了几个更好的 API 给我们使用,如下:
java.util.concurrent 包里面的 Executor, ThreadPoolExecutor 和 FutureTask.
————————————————————————————————————————————————
有些内容是官网的 API Guides 或者 reference 里面直接翻译过来的,包挂一些代码也是。翻译得可能不是很好,请见谅。
共同學習,寫下你的評論
評論加載中...
作者其他優質文章