欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android技术点记录-handler消息传递机制

程序员文章站 2022-07-14 19:59:19
...

一、相关的一些基本概念

 1. Android进程(该段内容来自网络参考)   

    当一个程序第一次启动的时候,Android会启动一个LINUX进程和一个主线程。默 认的情况下,所有该程序的组件都将在该进程和线程中运行。同时,Android会为每个应用程序分配一个单独的LINUX用户。Android会尽量保留一个正在运行进程,只在内存资源出现不足时,Android 会尝试停止一些进程从而释放足够的资源给其他新的进程使用, 也能保证用户正在访问的当前进程有足够的资源去及时地响应用户的事件。Android会根据进程中运行的组件类别以及组件的状态来判断该进程的重要 性,Android会首先停止那些不重要的进程。

按照重要性从高到低一共有五个级别:

前台进程
前台进程是用户当前正在使用的进程。只有一些前台进程可以在任何时候都存在。他们是最后一个被结束的,当内存低到根本连他们都不能运行的时候。一般来说, 在这种情况下,设备会进行内存调度,中止一些前台进程来保持对用户交互的响应。
可见进程
可见进程不包含前台的组件但是会在屏幕上显示一个可见的进程是的重要程度很高,除非前台进程需要获取它的资源,不然不会被中止。
服务进程
运 行着一个通过startService() 方法启动的service,这个service不属于上面提到的2种更高重要性的。service所在的进程虽然对用户不是直接可见的,但是他们执行了用 户非常关注的任务(比如播放mp3,从网络下载数据)。只要前台进程和可见进程有足够的内存,系统不会回收他们。
后台进程
运 行着一个对用户不可见的activity(调用过 onStop() 方法).这些进程对用户体验没有直接的影响,可以在服务进程、可见进程、前台进 程需要内存的时候回收。通常,系统中会有很多不可见进程在运行,他们被保存在LRU (least recently used) 列表中,以便内存不足的时候被第一时间回收。如果一个activity正 确的执行了它的生命周期,关闭这个进程对于用户体验没有太大的影响。
空进程
未运行任何程序组件。运行这些进程的唯一原因是作为一个缓存,缩短下次程序需要重新使用的启动时间。系统经常中止这些进程,这样可以调节程序缓存和系统缓 存的平衡。
Android 对进程的重要性评级的时候,选取它最高的级别。另外,当被另外的一个进程依赖的时候,某个进程的级别可能会增高。一个为其他进程服务的进程永远不会比被服 务的进程重要级低。因为服务进程比后台activity进程重要级高,因此一个要进行耗时工作的activity最好启动一个service来做这个工 作,而不是开启一个子进程――特别是这个操作需要的时间比activity存在的时间还要长的时候。例如,在后台播放音乐,向网上上传摄像头拍到的图片, 使用service可以使进程最少获取到“服务进程”级别的重要级,而不用考虑activity目前是什么状态。broadcast receivers做费时的工作的时候,也应该启用一个服务而不是开一个线程。

2、MessageQueue

     一个消息队列,采用先进先出的原则管理消息。每一个线程最多只可以拥有一个MessageQueue数据结构。 创建一个线程的时候,并不会自动创建其MessageQueue。通常使用一个Looper对象对该线程的MessageQueue进行管理。

      主线程创建时,会创建一 个默认的Looper对象,而Looper对象的创建,将自动创建一个Message Queue。其他非主线程,不会自动创建Looper,需要的时候,通过调用prepare函数来实现。 

3、Message

     消息对象,Message Queue中的存放的对象,handler接收和处理的对象。一个Message Queue中包含多个Message。 Message实例对象的取得,通常使用Message类里的静态方法obtain(),该方法有多个重载版本可供选择;它的创建并不一定是直接创建一个新的实例, 而是先从Message Pool(消息池)中看有没有可用的Message实例,存在则直接取出返回这个实例。如果Message Pool中没有可用的Message实例, 则用给定的参数创建一个Message对象。调用removeMessages()时,将Message从Message Queue中删除,同时放入到Message Pool中。除了上面这 种方式,也可以通过Handler对象的obtainMessage()获取一个Message实例。 

4、Looper

       每个线程只能有一个Looper。 

       Looper是MessageQueue的管理者,负责读取MessageQueue中的消息,读取到消息就交给handler进行处理。每一个MessageQueue都不能脱离Looper而存在,Looper对象的创建是通过prepare函数来实现的。  

       通过调用Looper.myLooper()可以获得当前线程的Looper对象,创建一个Looper对象时,会同时创建一个MessageQueue对象。除了主线程有默认的Looper,其他线程默认是没有MessageQueue对象的,所以,不能接收Message。如需要接收,自己定义一个Looper对象(通过prepare函数),这样该线程就有了自己的Looper对象和MessageQueue数据结构了。

      Looper 的prepare()方法保证每个线程最多只有一个Looper对象,然后通过loop()方法启动,loop()方法使用一个死循环不断的从MessageQueue中取出消息,并将取出的消息分给该消息对应的handler进行处理。
 

5、Handler

       消息的处理者,负责发送消息和处理消息。程序使用handler发送消息,被handler发送的消息必须被送到指定的MessageQueue(通过looper)。

      发送消息:

      handler负责将需要传递的信息封装成Message,通过调用handler对象的obtainMessage()来实现; 将消息传递给Looper,这是通过handler对象的sendMessage()来实现的。继而由Looper将Message放入MessageQueue中。

     接收处理消息:

     当Looper对象看到MessageQueue中含有Message,就将其广播出去。该handler对象收到该消息后,调用相应的handler对象的handleMessage()方法 对其进行处理。

6、消息处理

 Handler消息传递机制通过Thread、Handler、Looper、MessageQueue来实现:

          Looper、MessageQueue结合实现Message的管理、存放;

          Handler负责消息的发送、处理;

          Thread负责提供Handler、Looper运行的环境;

 

二、代码示例 

 

 1、通过其他线程来与UI线程进行通信,设置UI组件属性时

              UI线程接收消息、调用handler处理;(handleMessage)

              其他线程则通过handler发送特定消息给UI线程;(sendMessage)

UI线程默认自带Looper;直接设置handler处理即可。	
protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_base_handler);
		iv_handler_image = (ImageView) findViewById(R.id.iv_handle_image);
		final Handler handler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				if (msg.what == 0x12) {
					if (currId > imageIds.length - 1) {
						currId = 0;
					}
					iv_handler_image.setImageResource(imageIds[currId++]);
				}
			}
		};

		new Timer().schedule(new TimerTask() {
		
			@Override
			public void run() {
				// TODO Auto-generated method stub
				handler.sendEmptyMessage(0x12);
			}
		}, 0, 1000);
	}

 

 

 

  2、不同线程通过handler进行消息传递

              调用方:

                     启动线程(或者预先启动),并sendMessage;

              处理方:

                     实现handler,handleMessage

 

 

自定义线程,在该线程中定义Looper,并且将Looper与Handler绑定
一个线程只能定义一个Looper
public class MyHandlerThread implements Runnable {
	MyHandler handler=null;
	Looper mylooper=null;
	@Override
	public void run() {
		Looper.prepare();
		mylooper=Looper.myLooper();
		handler=new MyHandler(mylooper);
		Looper.loop();
	}

	@Override
	protected void finalize() throws Throwable {
		// TODO Auto-generated method stub
		super.finalize();
		mylooper.quit();
	}
}

 

Handler处理过程;处理完成后可以通过广播方式往外传递消息
public class MyHandler extends Handler{

	public MyHandler(Looper looper){
		super(looper);
	}
	
	@Override
	public void handleMessage(Message msg) {
		Log.i("myhandler", msg.getData().getString("data"));
	}
}

 

 

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_base_handler);
		iv_handler_image = (ImageView) findViewById(R.id.iv_handle_image);
		final MyHandlerThread mythread=new MyHandlerThread();
		//启动线程
               new Thread(mythread).start();
		new Timer().schedule(new TimerTask() {
		
			@Override
			public void run() {
				// TODO Auto-generated method stub
				Bundle bundle=new Bundle();
				bundle.putString("data", "我是数据");
				Message mess=new Message();
				mess.setData(bundle);
				mythread.handler.sendMessage(mess);
			}
		}, 0, 1000);
	}