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就有可能为 NULLn对于子线程使用 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里面的非 NULLMessagen  一开始 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());               }                    } }


更多相关文章

  1. Android支持HTML标签
  2. android文本内容自动朗读实例教程
  3. android利用线程池高效实现异步任务
  4. andr
  5. Android进阶知识:Handler相关
  6. FastBoot 刷机方法
  7. Android(安卓)Service生命周期及用法!
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. 经典button布局
  2. 去掉tabhost横线
  3. Android很有用的代码片段
  4. Android(安卓)EditText输入内容时挤压上
  5. android 进入页面隐藏输入法
  6. 解决INSTALL_FAILED_INSUFFICIENT_STORAG
  7. [置顶] android滑动基础篇
  8. 介绍三个Android支持库控件:TabLayout+Vie
  9. Android(安卓)命令行手动编译打包详解
  10. android 获取api key