Android中的进程(Process)和线程(Thread)

一、进程(process)

1.默认情况下,每个application都运行在一个独立的process中,所有的component都运行在该process中的主线程中(main线程,由于主要处理UI,所以也叫UI线程)
2.可以在manifest文件中通过component的android:process属性为当前组件指定运行的process,甚至不同application中的组件都可以运行在同一个process中,
  但大多数应用,我们不应该这样去配置,除非你确实想让你的某些组件在单独的process中被管理
3.android系统会在资源不足的情况下kill掉某些他认为可以kill的process在为用户正在执行的动作提供资源,
  一般process有5个重要性级别,低级别的process最先被kill
4.process的5个重要性级别
 1)foreground process : 具有以下特征的process被认为是前台进程(foreground process)
  ①最高拥有一个处于onResume()状态的activity
  ②最高拥有和用户交互的activity绑定的service
  ③最高拥有正在运行的前台service(调用了startForeground()的正在运行的service)
  ④最高拥有正在执行生命周期方法的service:例如:onCreate(),onStart(),onDestroy()
  ⑤最高拥有正在执行onReceive()方法的BroadcastReceiver
 2)visible process : 可见级别的进程
  ①最高拥有一个activity处于onPause()状态
  ②最高拥有一个前台service或者是绑定到activity的service
 3)Service process :
  ①最高拥有正在运行的service,这些service是通过startService()启动的
 4)background process :
  ①最高拥有不可见的activity(处于onStop()状态)
 5)Empty process :
  ①只拥有那些并没有任何component的process,这些process一般是用来当做临时缓存用的

二、线程(Thread)

1.一个application启动时,它运行在一个独立process中的main线程中,main线程是一个非常重要的线程,它管理着事件的产生,分发和处理,
  用于与application的交互都是在这个线程中处理的,所以该线程又被称作UI线程(UI Thread)
2.默认的,一个application中所有的component都运行在UI Thread中,系统对不同component的调用都是通过UI Thread来转发的,所以必然的,
 那些系统调用的方法,比如onClick(),onKeyDown()等等,都是在UI Thread中执行的
3.如果你的application需要处理长事件的操作,那么单线程的模式将使你的application 用户体验降低,尤其是例如:网络操作,数据库操作等等
 他们一般耗时比较长,在UI Thread中运行的话容易block掉,并且在android系统中如果UI Thread被block超过5秒钟,系统将抛出臭名昭著的application not responding 异常

★★★★★UI Thread 宗旨:
1.一定不要block UI Thread :数据库操作,网络操作等都应该另起线程来完成
2.一定不要在 UI Thread以外的其它thread中去access UI Toolkit (UI toolkit也就是那些android.widget and android.view packages中的component)
 

三、Worker threads (工作线程)
1.正如上面提到的,一定不要阻塞UI Thread,所以只要你的工作不是瞬时完成的,都应该另起一个线程来实现:如下在事件处理函数中建立一个新的工作线程
 public void onClick(View v) {
  new Thread(new Runnable() {
   public void run() {
    Bitmap b = loadImageFromNetwork("http://example.com/image.png");
    mImageView.setImageBitmap(b);//违反UI Thread第二条规则
   }
  }).start();
 }
2.由于不能在UI Thread以外的线程中,所以上面的例子代码虽然开辟了一个新的线程,不会阻塞UI Thread,但是却在工作线程中操作UI Toolkit中的component,
  所以违反了第二个规则,android提供了多种解决方案:
 1)第一类解决方案:通过在代码的不同位置调用不同的方法,有点结构化编程的感觉,大量类似处理会使得代码可读性和可维护性降低
  ①Activity.runOnUiThread(Runnable)
  ②View.post(Runnable)
   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();
   }

  ③View.postDelayed(Runnable, long)
 
 2)第二类解决方案:使用Handler来统一的处理Message实现线程调度,但还不是最好的方式
  ④Handler处理Message
 
 3)第三种解决方案:异步的工作AsyncTask,这是也许是最好的解决方案
  创建一个继承自AsyncTask 的类,并实现它的两个方法,分别用来处理工作线程处理的任务和UI线程处理的任务。
  同时避免了你自己来操作线程和(或者)Handler的麻烦
   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的快速入门
  (1).You can specify the type of the parameters, the progress values, and the final value of the task, using generics
  (2).The method doInBackground() executes automatically on a worker thread
  (3).onPreExecute(), onPostExecute(), and onProgressUpdate() are all invoked on the UI thread
  (4).The value returned by doInBackground() is sent to onPostExecute()
  (5).You can call publishProgress() at anytime in doInBackground() to execute onProgressUpdate() on the UI thread
  (6).You can cancel the task at any time, from any thread
  ★★★★★
  很多操作会导致work thread意外重启,比如:runtime configuration change(如:用户改变屏幕方向等可能会destroy掉你的work thread,然后reStart)
  在这种情况下,关于如何正确的persist 你的task,以及如何正确的cancle task 请参考源代码例子:Shelves
  API: http://code.google.com/p/shelves/
  源代码可以在GIT上下载

四、AsyncTask :异步的Task,android通过它来实现UI Thread和work thread的独立处理,推荐方式
 1)AsyncTask enables proper and easy use of the UI thread.
    This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
 
 2)An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread.
    An asynchronous task is defined by 3 generic types, called Params, Progress and Result,
     and 4 steps, called onPreExecute, doInBackground, onProgressUpdate and onPostExecute.

 3)AsyncTask must be subclassed to be used. The subclass will override at least one method (doInBackground(Params...)),
    and most often will override a second one (onPostExecute(Result).)
 
 4)例子:
  (1)定义AsyncTask
   private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
    protected Long doInBackground(URL... urls) {
     int count = urls.length;
     long totalSize = 0;
     for (int i = 0; i < count; i++) {
      totalSize += Downloader.downloadFile(urls[i]);
      publishProgress((int) ((i / (float) count) * 100));
     }
     return totalSize;
    }

    protected void onProgressUpdate(Integer... progress) {
     setProgressPercent(progress[0]);
    }

    protected void onPostExecute(Long result) {
     showDialog("Downloaded " + result + " bytes");
    }
   }
  (2)执行
   new DownloadFilesTask().execute(url1, url2, url3);


 5)AsyncTask's generic types : 泛型参数的意义
    The three types used by an asynchronous task are the following:

  1.Params, the type of the parameters sent to the task upon execution.
  2.Progress, the type of the progress units published during the background computation.
  3.Result, the type of the result of the background computation.
 
  Not all types are always used by an asynchronous task. To mark a type as unused, simply use the type Void:
  private class MyTask extends AsyncTask<Void, Void, Void> { ... }
 
 6)AsyncTask执行的4步骤:The 4 steps
  When an asynchronous task is executed, the task goes through 4 steps:
  1.onPreExecute()
    invoked on the UI thread immediately after the task is executed.
    This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
  2.doInBackground(Params...)
    invoked on the background thread immediately after onPreExecute() finishes executing.
    This step is used to perform background computation that can take a long time.
    The parameters of the asynchronous task are passed to this step.
    The result of the computation must be returned by this step and will be passed back to the last step.
    This step can also use publishProgress(Progress...) to publish one or more units of progress.
    These values are published on the UI thread, in the onProgressUpdate(Progress...) step.
  3.onProgressUpdate(Progress...)
    invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined.
    This method is used to display any form of progress in the user interface while the background computation is still executing.
    For instance, it can be used to animate a progress bar or show logs in a text field.
  4.onPostExecute(Result)
    invoked on the UI thread after the background computation finishes.
    The result of the background computation is passed to this step as a parameter.
   
 7)Cancelling a task : 取消Task的执行
  A task can be cancelled at any time by invoking cancel(boolean).
  Invoking this method will cause subsequent calls to isCancelled() to return true.
  After invoking this method, onCancelled(Object),
  instead of onPostExecute(Object) will be invoked after doInBackground(Object[]) returns.
  To ensure that a task is cancelled as quickly as possible,
  you should always check the return value of isCancelled() periodically from doInBackground(Object[]),
  if possible (inside a loop for instance.)

 8)Threading rules :异步Task正常工作的前提
    There are a few threading rules that must be followed for this class to work properly:
  (1).The task instance must be created on the UI thread.
  (2).execute(Params...) must be invoked on the UI thread.
  (3).Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...) manually.
  (4).The task can be executed only once (an exception will be thrown if a second execution is attempted.)
     
   
 9)Memory observability :线程同步的资源
  AsyncTask guarantees that all callback calls are synchronized in such a way that the following operations are safe without explicit synchronizations.
  (1).Set member fields in the constructor or onPreExecute(), and refer to them in doInBackground(Params...).
  (2).Set member fields in doInBackground(Params...), and refer to them in onProgressUpdate(Progress...) and onPostExecute(Result).

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值