进程(一) 1.2 Android中异步处理大杀器——Handler(1)

Android中处理异步的第一选择和最佳选择,就是AsynTask这个类,因为他使用起来最方便,安全。

再介绍另外一个在开发中用的很多的异步大杀器,用于处理异步消息的,处理一些耗时操作,处理后台运行的程序并且要更新ui的情况,他就是Handler。
Handler主要接受子线程发送的数据, 并用此数据配合主线程更新UI.。

当应用程序操作应用程序的时候,出现一些比较耗时的操作,譬如 从网上下载数据,读取本地较大的文件,这时不能把这些操作 放在主线程,因为这样会阻塞主线程,而且如果5秒钟还没有完成的话,就会出席那ANR(应用程序无响应)的错误。所以我们需要把耗时操作放在子线程进行操作。这样是可以处理了主线程被阻塞的麻烦,但是如果如果我们想更新UI,而在子线程中操作是不安全的,无法预料后面发生的事情(Andoid UI toolkit不是线程安全的,所以注意在android使用线程的两个点:a > 不要阻塞UI线程; b > 不要再主线程外的线程操控UI线程(即更新UI)),这个时候就体现出了Handler的价值了。

Handler是在主线程(UI线程)中运行,他与子线程通过Message来传递数据(通过SendMessage()发送个主线程),而主线程中有个消息队列MessageQueue来存储,HandleMessage()一个一个的从队列中取出消息,并相应的进行处理,更新ui。

当创建了Handler对象,他就会与他所在的线程以及消息队列进行绑定,这样发送Message或Runable,就可以发送给消息队列做相应的处理了。一个线程可以有多个handler,各自处理各自的相对应的消息;但是一个线程只有一个looper,当然也就只有一个消息循环。这里还要注意一个问题,在一个普通的子线程中创建handler,因为没有调用Looper.prepare(),没有Looper实例,所以会出现异常,同时这也说明一个普通的子线程没有Looper实例,没有消息循环。所以在一个普通的子线程中发送消息是不行的,当然我们可以自己创建Looper实例(a.子线程中创建一个消息队列(就是Looper对象,通过prepare(),loop()); b.得到主线程中得消息队列,操控主线程的消息队列Looper.getMainLooper())。但是我们一般这么做,而是使用另外一个类,叫做HandlerThread,这个自身有Looper实例。


看下下面的代码片段:

public class HandlerDemo extends Activity {
	private final static int MESSAGE_ID = 5;
	
	private TestHandler1 mTestHandler1;
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		mTestHandler1 = new TestHandler1();  // 创建handler实例
		
		
		Button btn = (Button) findViewById(R.id.clcik);
		
		btn.setOnClickListener(new View.OnClickListener(){

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				new Thread(new Runnable(){                // 从子线程发送消息给ui线程        

					@Override
					public void run() {
						// TODO Auto-generated method stub
						// 发送消息
						// 直接从handler获取message对象,当然也可以new一个,但是推荐前一个
						Message msg = mTestHandler1.obtainMessage();              
						Bundle b = new Bundle();
						b.putString("color", "red");
						// 给handler发送的数据,放入message中
						msg.setData(b);
						msg.what = MESSAGE_ID;
						mTestHandler1.sendMessage(msg);                        
					}
					
				}).start();
			}
			
		});
	}
	
	private class TestHandler1 extends Handler    // 实现handler          
	{

		@Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			super.handleMessage(msg);
			if (msg.what == MESSAGE_ID) {                  
				Bundle b = msg.getData();
				String colorStr = b.getString("color");
				Log.d("HandlerDemo", "TestHandler1---------"+colorStr);
			}
		}
		
	}
	
}

继承于handler的子类TestHandler1,并在主线程中分别创建对象;

创建一个子线程,在子线程用主线程中定义的mTestHandler1对象,发送消息给主线程,并在主线程中的HandleMessage中做相应的处理;

Message msg = mTestHandler1.obtainMessage();               
Bundle b = new Bundle();
b.putString("color", "red");
// 给handler发送的数据,放入message中
msg.setData(b);
msg.what = MESSAGE_ID;
mTestHandler1.sendMessage(msg);   
这一部分会在Message中做相应的介绍,这里就不解释了。

总结:

1.handler的作用(为什么使用handler):

1)按计划发送消息或执行某个Runnanble(使用POST方法),类似定时器
2)从其他线程中发送来的消息放入消息队列中,避免线程冲突(常见于更新UI线程);

2.当handler在一个线程中创建,就会与他所在的线程和消息队列进行绑定;

3.一个线程对应一个Looper(消息循环),一个MessageQueue(消息队列)

4.一个线程中可以对应多个handler,但是共用一个Looper和MessageQueue;

5.handler可以从任何线程发送消息(前提必须有looper实例);

你可能感兴趣的:(thread,UI,android,String,Class,button)