在本篇文章中将会介绍到的内容有:


1.介绍多线程用处


2.线程的基本用法


3.简单讲解异步消息处理机制(用于更新UI)




1.多线程


当我们需要执行一些耗时操作时,如果单纯的将耗时操作交给主线程去做,那么有可能别的一些更需要主线程做的任务就被耽搁了(如UI的更新),导致了主线程被阻塞,影响了用户对软件的正常使用。所以需要将一些耗时的操作分配给子线程去做,提高软件的友好性。




2.线程的基本用法


线程的基本用法主要有3种:




(1)写个类继承Thread,然后重写父类的run()方法,在其中写上耗时逻辑


   

class MyThread extends Thread{
 
          @Override
 
          public void run(){
 
               //处理具体的逻辑
 
          }
 
     }


启动该线程的方法:


     new MyThread().start();




上述方法因为是使用了继承的方式,所以耦合性比较高,并不推荐使用。




(2)选择实现Runnable接口来降低耦合


   

class MyThread implements Runnable{
 
          @Override
 
          public void run(){
 
               //处理具体的逻辑
 
          }
 
     }


启动该线程的方法:


MyThread myThread = new MyThread();


     new Thread(myThread).start();




(3)使用匿名类的方式,这种方法更为常见


     new Thread(new Runnable (){


          @Override


       

public void run(){
 
               //处理具体的逻辑
 
          }
 
     }.start();




3.简单讲解异步消息处理机制(用于更新UI)


首先要明确的一点是在android中对于UI的更新,是不允许在子线程中执行的,会发生错误,只能在主线程中进行执行。子线程中做耗时的操作,在主线程中做UI的更新。


用一个小的demo介绍一下


public class HandlerActivity extends Activity { 
 
 

  public static final int UPDATE_TEXT = 1; 

 

  private Button mButton; 

 

  private TextView mTextView; 

 

  private Handler handler = new Handler(){ 

 
 
 
 

  //处理消息在主线程中 

 

  @Override 

 

  public void handleMessage(Message msg) { 

 

  // TODO Auto-generated method stub 

 
 
 
 

  switch (msg.what) { 

 

  case UPDATE_TEXT: 

 

       mTextView.setText("it is changed"); 

 

       break; 

 
 
 
 

  default: 

 

       break; 

 

  } 

 

  } 

 

  }; 

 
 
 
 

  @Override 

 

  protected void onCreate(Bundle savedInstanceState) { 

 

  // TODO Auto-generated method stub 

 

  super.onCreate(savedInstanceState); 

 

  setContentView(R.layout.layout_handler); 

 
 
 
 

  mButton = (Button)findViewById(R.id.change_text); 

 

  mTextView = (TextView)findViewById(R.id.handle_textView); 

 
 
 
 

  mButton.setOnClickListener(new OnClickListener() { 

 
 
 
 

  @Override 

 

  public void onClick(View v) { 

 

  // TODO Auto-generated method stub 

 

  new Thread(new Runnable() { 

 
 
 
 

  //子线程运行下面的代码 

 

  @Override 

 

  public void run() { 

 

  // TODO Auto-generated method stub 

 

  Message message = new Message(); 

 

  message.what = UPDATE_TEXT; 

 

  handler.sendMessage(message); 

 
 
 
 

  //子线程运行耗时操作,修改UI的操作放在handler的主线程中处理 

 

  try { 

 

       Thread.sleep(1000); 

 

  } catch (InterruptedException e) { 

 

       // TODO Auto-generated catch block 

 

       e.printStackTrace(); 

 

  } 

 

  } 

 

  }).start(); 

 

            } 

 

  }); 

 

  } 

 

  }



上述的异步消息处理机制需要我们理解4个概念,handler、message、MessageQueue、looper


  • handler : 是整个异步消息处理机制中的控制者,处理者。它负责发送和处理消息
  • message : 主要是在不同的线程之间传递消息,作为一个消息的载体,其中的what字段等等,可以携带一定的数据信息。
  • MessageQueue: 消息队列,整个程序可能有很多异步消息需要处理,但是对于一个线程来说(主线程),只能有一个handler ,MessageQueue。所以我们需要把还没有处理的消息放入消息队列当中。
  • looper:它相当于MessageQueue中的调度者,通过调用loop方法,进行一个无限循环,不断的从消息队列中取出消息,发送给 handler进行处理。

我们再对异步消息处理的流程梳理一遍。首先要在主线程中创建一个Handler对象,并重写handleMessage()方法。然后当子线程需要更新UI时,就创建一个Message对象,通过Handler对象将这条信息发送出去。之后这条信息会被添加到MessageQueue队列中等待被处理,而Looper会一直尝试从MessageQueue中取出待处理消息,分发回Handler的handleMessage()方法中去。由于Handler是在主线程中创建的,所以此时handleMessage()方法也是在主线程中运行的,于是我们可以放心的更新UI操作。


关于Handler异步消息处理机制的简单讲解可以查看: http://android.jobbole.com/80853/


深入讲解可查看: (比较深入,还不怎么明白)


对于异步消息处理机制,android中还提供了一个AsyncTask,这个机制更加简洁方便,详细可参考:    (demo中有一句问题,要注意)


也可参看我下一篇关于AsyncTask的介绍和使用