在Android中应用到多线程通信,尤其是新的线程去更新主线程的UI,因为新线程无法直接更新widget, 所以在Android多应用handler处理多线程的通信。
Handler主要有两个作用,一是安排消息或者Runnable在某个主线程中某个地方执行,二是安排一个任务去别的线程工作。
提到Handler肯定会设计到Looper,Looper的作用就是替对应的Handler管理消息,每一个Handler都有一个属于自己的Looper,这是一个对一的关系,在Android中除了主线程外其他线程在使用时不会自动为handler分配Looper的,所以在新的线程应用Handler的时候必须首选Looper.prepare函数来初始化Looper,然后用loop()函数来做信息循环的处理。
MessageQueue是控制所属线程的消息,所有的message并不是直接会存储在MeesageQueue中,通过Looper工作的。MessageQueue, Looper
Handler三者是一对一的关系,并且他们三个和某一个所属的线程也是一对一的关系,每个线程都有自己的一套Handler机制 。
具体的消息运行机制是Looper将发出的消息放到MessageQueue中,然后循环的传递给Handler,Handler会将当前的Message进行处理,然后做出相应的反应。
其实无论怎样发送,他们的重点只是一条,用的哪个handler发送的消息,就由这个handler处理消息,这个线程所处的线程做出相应的反应。handler和thread是绑定的一对>一关系。 想让线程接收什么,就用线程所属的handler发送消息。
例如子线程给主线程发送消息更新UI 和主线程给子线程发送信息:
public class MainActivity extends Activity implements OnClickListener { private MyHandler mHandler = null; private Button btn1; private TextView mText; private HanderThread myThread; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn1 = (Button) findViewById(R.id.button1); mText = (TextView) findViewById(R.id.textview); btn1.setOnClickListener(this); mHandler = new MyHandler(Looper.getMainLooper()); } @Override public void onClick(View v) { // TODO Auto-generated method stub switch(v.getId()){ case R.id.button1: myThread = new HanderThread(); myThread.start(); } } class MyHandler extends Handler{ public MyHandler(Looper looper){ super(looper); } public void handleMessage(Message msg){ //此函数处理handler发送的消息。 switch(msg.what){ case 4: String obj = msg.getData().getString("senddata"); mText.setText("receive "+obj); break; default: break; } } } class HanderThread extends Thread{ HanderThread (){ } public void run(){ // 在这里你可以做一些费时的操作,本例只是在这里发送了一个 //消息给主线程告诉它消息来自子线程,并改变TextView中的文字。 String msg = "from child thread"; Bundle mBundle = new Bundle(); Message Msg = mHandler.obtainMessage(); mBundle.putString("senddata",msg); Msg.what = 4; Msg.setData(mBundle); //要记住这里发送这个message的是mHandler,这个handler是 //属于主线程的handler所以主线程来处理这个消息。并且有主线程 //来做出相应的改变。 mHandler.sendMessage(Msg); } }
public class MainActivity extends Activity { private Handler mMainHandler = null; private TextView info = null; private Button msgBtn = null; ChildThread child1 = null; class ChildThread extends Thread { private Handler childHander = null; private String CHILD_TAG = "ChildThread"; public void run() { this.setName("ChildThread"); // 初始化消息循环队列,需要在Handler创建之前 //必须用这个函数和loop(),否则报错。 Looper.prepare(); childHander = new Handler() { @Override public void handleMessage(Message msg) { // 在子线程中可以做一些耗时的工作 String sMsg = ""; Message toMain = new Message(); // mMainHandler.obtainMessage(); toMain.obj = "This message from " + this.getLooper().getThread().getName() + " the main thread had sent " + (String) msg.obj; // 这个消息是主线程的handler发送的,由主线程处理,这里 //主要是改变主线程TextView的文字。 mMainHandler.sendMessage(toMain); } }; //使消息开始循环。 Looper.loop(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); info = (TextView) findViewById(R.id.info); msgBtn = (Button) findViewById(R.id.bt1); mMainHandler = new Handler() { @Override public void handleMessage(Message msg) { // 处理收到的消息。 info.setText((String) msg.obj); } }; child1 = new ChildThread(); child1.start(); msgBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (child1.childHander != null) { // 发送消息给子线程 Message childMsg = child1.childHander.obtainMessage(); Message msg = new Message(); msg.obj = mMainHandler.getLooper().getThread().getName() + " say hello"; // 因为发送这个小时的handler是子线程的所有子线程处理。 // 哪个线程处理消息要看是由属于哪个线程的handler发出的消息。 child1.childHander.sendMessage(msg); } } }); } }