android多线程编程总结

n
Android中,只要是关于UI相关的东西,就不能放在子线程中,因为子线程是不能操作UI的,只能进行数据、系统等其他非UI的操作。 
n 在单线程模型下,为了解决类似的问题,Android设计了一个Message Queue(消息队列), 线程间可以通过该Message Queue并结合HandlerLooper组件进行信息交换。下面将对它们进行分别介绍
n andriod提供了 Handler 和 Looper 来满足线程间的通信。例如一个子线程从网络上下载了一副图片,当它下载完成后会发送消息给主线程,这个消息是通过绑定在主线程的Handler来传递的。
n Message消息,线程间交流的信息,处理数据后台线程需要更新UI,则发送Message内含一些数据给UI线程。 
public final class Message implements Parcelable {
    public int what;
    public Messenger replyTo;
    long when;
    Bundle data;
    Handler target;     
    Runnable callback;
    Message next;
    private static Object mPoolSync = new Object();
    private static Message mPool;
    private static int mPoolSize = 0;
    private static final int MAX_POOL_SIZE = 10;
When: Handler发送Message生成的时间
Data: Bundler 对象上绑定要线程中传递的数据
Next: 当前Message 对一下个Message 的引用
Handler: 处理当前Message Handler对象.
mPool: 通过字面理解可能叫他Message,但是通过分析应该叫有下一个Message引用的Message链更加适合.
其中Message.obtain(),通过源码分析就是获取断掉Message链关系的第一个Message.

Handler承担着接受子线程传过来的 (子线程用 sedMessage()sendEmptyMessage方法传弟 )Message对象 (里面包含数据 ),把这些消息放入主线程队列中,配合主线程进行更新 UI
n使用 Handler,需要 implement 该类的  handleMessage(Message)方法,它是处理这些 Message的操作内容,例如 Update UI。通常需要子类化 Handler来实现 handleMessage方法。 
n Handler 可以分发 Message 对象和 Runnable 对象到主线程中 每个 Handler , 都会绑定到创建他的线程中 ( 一般是位于主线程 ),
n它有两个作用 :
¨  安排消息或 Runnable 在某个主线程中某个地方执行 ,
¨安排一个动作在不同的线程中执行


n Message Queue消息队列,用来存放通过 Handler发布的消息,按照先进先出执行。
n    每个 message queue都会有一个对应的 HandlerHandler会向 message queue通过两种方法发送消息: sendMessagepost。这两种消息都会插在 message queue队尾并按先进先出执行。但通过这两种方法发送的消息执行的方式略有不同:通过 sendMessage发送的是一个 message对象 ,会被 HandlerhandleMessage()函数处理;而通过 post方法发送的是一个 runnable对象,则会自己执行。


n Looper是每条线程里的 Message Queue的管家。 Android没有 GlobalMessage  Queue,而 Android会自动替主线程 (UI线程 )建立 Message Queue,但在子线程里并没有建立 Message Queue。所以调用 Looper.getMainLooper()得到的主线程的 Looper不为 NULL,但调用 Looper.myLooper()得到当前线程的 Looper就有可能为 NULL
n对于子线程使用 LooperAPI Doc提供了正确的使用方法:
class   LooperThread   extends   Thread   {  
     public   Handler   mHandler;   
     public   void   run()   {  
         Looper.prepare();   //创建本线程的 Looper并创建一个 MessageQueue  
         mHandler   =   new   Handler()   {  
             public   void   handleMessage(Message   msg)   {  
                 //   process   incoming   messages   here  
             }  
         };     
         Looper.loop();   //开始运行 Looper,监听 Message   Queue  
     }  
}    


nLooper.loop()方法运行开始后,循环地按照接收顺序取出 Message Queue里面的非 NULLMessage
n  一开始 Message Queue里面的 Message都是 NULL的。当 Handler.sendMessage(Message)Message Queue,该函数里面设置了那个 Message对象的 target属性是当前的 Handler对象。随后 Looper取出了那个 Message,则调用该 Messagetarget指向的 HanderdispatchMessage函数对 Message进行处理。
¨    在 dispatchMessage方法里,如何处理 Message则由用户指定,三个判断,优先级从高到低:
n   Message里面的 Callback,一个实现了 Runnable接口的对象,其中 run函数做处理工作;
n   Handler里面的 mCallback指向的一个实现了 Callback接口的对象,由其 handleMessage进行处理;
n    理消息 Handler对象对应的类继承并实现了其中 handleMessage函数,通过这个实现的 handleMessage函数处理消息。
n     Handler处理完该 Message (update UI) 后, Looper则设置该 MessageNULL,以便回收!


Android
使用 mHandler = new MyHandler(Looper.getMainLooper());  可诞生用来处理 main线程的 Handler对象;其中, MyHandler是自已实现的 Handler的子类别。 
同线程内不同组件间的消息传递
public class Activity1 extends Activity implements OnClickListener{
       Button button = null;
       TextView text = null;
       @Override
       protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity1);        
              button = (Button)findViewById(R.id.btn);
              button.setOnClickListener(this);
              text = (TextView)findViewById(R.id.content);
       } 
public void onClick(View v) {
              switch (v.getId()) {
              case R.id.btn:
                     Looper looper = Looper.myLooper();//取得当前线程里的looper
                     MyHandler mHandler = new MyHandler(looper);//构造一个handler使之可与looper通信
                    mHandler.removeMessages(0);
                     String msgStr = "主线程不同组件通信:消息来自button";
                     Message m = mHandler.obtainMessage(1, 1, 1, msgStr);//构造要传递的消息
                     mHandler.sendMessage(m);//发送消息:系统会自动调用handleMessage方法来处理消息
                     break; 
              }            
       }     
       private class MyHandler extends Handler{             
              public MyHandler(Looper looper){
                     super(looper);
              }           
              public void handleMessage(Message msg) {//处理消息
                     text.setTex
                        ……
                }
        }

子线程传递消息给主线程
  private   class   MyThread   extends   Thread{
                      public   void   run() {
                      Looper curLooper = Looper. myLooper ();
                      Looper mainLooper = Looper. getMainLooper ();
                      String msg ;
                      if(curLooper==null){
                             mHandler   =   new   MyHandler(mainLooper);
                             msg =   "curLooper is null";
                      }else{
                             mHandler   =   new   MyHandler(curLooper);
                             msg =   "This is curLooper";
                      }
                      mHandler.removeMessages(0);
                      Message m =   mHandler.obtainMessage(1, 1, 1, msg);
                      mHandler.sendMessage(m);
               }             
        }
}


Android另外提供了一个工具类:AsyncTask。它使得UI thread的使用变得异常简单。它使创建需要与用户界面交互的长时间运行的任务变得更简单,不需要借助线程和Handler即可实现。 
 AsyncTask的构造函数的参数设置需要看明白:AsyncTask 
Params对应doInBackground(Params...)的参数类型。而new AsyncTask().execute(Params... params),就是传进来的Params数据,你可以execute(data)来传送一个数据,或者execute(data1, data2, data3)这样多个数据。
 Progress对应onProgressUpdate(Progress...)的参数类型;
 Result对应onPostExecute(Result)的参数类型。
 当以上的参数类型都不需要指明某个时,则使用Void,注意不是void。
实现AsyncTask中定义的下面一个或几个方法
onPreExecute() 开始执行前的准备工作;
doInBackground(Params...) 开始执行后台处理,可以调用publishProgress方法来更新实时的任务进度;
onProgressUpdate(Progress...)  在publishProgress方法被调用后,UI thread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
 onPostExecute(Result) 执行完成后的操作,传送结果给UI 线程。
 这4个方法都不能手动调用。而且除了doInBackground(Params...)方法,其余3个方法都是被UI线程所调用的,所以要求:
 AsyncTask的实例必须在UI thread中创建;
 AsyncTask.execute方法必须在UI thread中调用;

((Button) findViewById(R.id.load_AsyncTask)).setOnClickListener(new View.OnClickListener(){ 
 
    @Override 
    public void onClick(View view) { 
        data = null; 
        data = new ArrayList();  
        adapter = null;  
        //显示ProgressDialog放到AsyncTask.onPreExecute()里 
        //showDialog(PROGRESS_DIALOG); 
        new ProgressTask().execute(data); 
    } 
});  
private class ProgressTask extends AsyncTask, Void, Integer> { 
 
/* 该方法将在执行实际的后台操作前被UI thread调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条。*/ 
@Override 
protected void onPreExecute() { 
    // 先显示ProgressDialog
    showDialog(PROGRESS_DIALOG); 
 
/* 执行那些很耗时的后台计算工作。可以调用publishProgress方法来更新实时的任务进度。 */ 
@Override 
protected Integer doInBackground(ArrayList... datas) { 
    ArrayList data = datas[0]; 
    for (int i=0; i<8; i++) { 
        data.add("ListItem"); 
    } 
    return STATE_FINISH; 
}  
/* 在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用,  后台的计算结果将通过该方法传递到UI thread. 
 * */  
protected void onPostExecute(Integer result) { 
    int state = result.intValue(); 
    switch(state){ 
    case STATE_FINISH: 
        dismissDialog(PROGRESS_DIALOG); 
        Toast.makeText(getApplicationContext(),   "加载完成!", Toast.LENGTH_LONG)
             .show(); 。。。。。。
        break; 
         
    case STATE_ERROR: 
       dismissDialog(PROGRESS_DIALOG); 
       Toast.makeText(getApplicationContext(), "处理过程发生错误!",Toast.LENGTH_LONG).show(); 。。。。。
          break;   default:   }

              public void handleMessage(Message msg) {//处理消息
                     text.setText(msg.obj.toString());
              }            
       }
}



你可能感兴趣的:(android,多线程,android,开发)