Android线程间通信之Handler

Handler机制及基本使用也已经是老生常谈了~~~

1、概述

Android中拒绝子线程中更新UI。且主线程中过多执行耗时操作会造成界面卡顿导致ANR影响用户体验,因此Handler线程间通信的信使应运而生。Handler有两个主要用途:(1)调度消息和runnable对象作为将来的执行;及(2)将被执行在一个不同的线程自己的方法。

1.Handler基本原理

主线程(UI线程)
子线程(work线程)
Message 消息类
MessageQueue消息队列(数据结构中的队列,先进先出规则)
这里写图片描述

Handler对象发送消息对象到消息队列中,Looper循环取出消息队列中的消息对象,并将该消息对象设置为发送该消息对象的handler的handleMessage方法的参数,若消息队列中没有消息则处于阻塞状态。

2、Handler的基本使用

1.UI线程中发送消息并在UI线程中执行

Handler发送和处理消息的几个方法:

   void  handleMessage(Message  msg):处理消息的方法,该方法通常被重写。
   final boolean hasMessage(int  what):检查消息队列中是否包含有what属性为指定值的消息
   final boolean hasMessage(int what ,Object object):检查消息队列中是否包含有what好object属性指定值的消息
   sendEmptyMessage(int what):发送空消息
   final Boolean send EmptyMessageDelayed(int what ,long delayMillis):指定多少毫秒发送空消息
   final  boolean sendMessage(Message msg):立即发送消息
   final boolean sendMessageDelayed(Message msg,long delayMillis):多少秒之后发送消息

由于代码比较简单,直接上代码了~

/**
 * Created by magic on 2016年10月23日.主线程中发送消息主线程中接收
 */
@SuppressLint("HandlerLeak")
public class MainActivity extends Activity {

	TextView textView;
	Button button;
	Handler handler = new Handler() {
		// 接收消息并处理
		public void handleMessage(Message msg) {
			System.out.println(Thread.currentThread().getName());
			// main
			System.out.println("消息->" + msg.arg1 + "-" + msg.obj);
			// 消息->1-obj消息
		};
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		button = (Button) findViewById(R.id.btn);
		button.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View arg0) {
				// 主线程中发送消息
				Message message = handler.obtainMessage();
				message.arg1 = 1;
				message.obj = "obj消息";
				handler.sendMessage(message);
				// 输出当前线程名称
				System.out.println(Thread.currentThread().getName());
				// main
			}
		});
	}

}
2.Work线程中发送消息并在UI线程中执行
/**
 * Created by magic on 2016年10月23日.Work线程中发送消息 UI线程中接收消息
 */
@SuppressLint("HandlerLeak")
public class TwoActivity extends Activity {

	Button button;
	Handler handler = new Handler() {
		// 接收消息并处理
		public void handleMessage(Message msg) {
			System.out.println(Thread.currentThread().getName());
			// main
			System.out.println("消息->" + msg.arg1 + "-" + msg.obj);
			// 消息->1-obj消息
		};
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		button = (Button) findViewById(R.id.btn);
		button.setText("Work->UI");
		button.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View arg0) {
				Thread thread = new Thread(new Runnable() {

					@Override
					public void run() {
						// work线程中发送消息
						Message message = handler.obtainMessage();
						message.arg1 = 1;
						message.obj = " obj消息";
						System.out.println(Thread.currentThread().getName());
						// Thread-400
						handler.sendMessage(message);
						// 输出当前线程名称
					}
				});
				// 开启线程
				thread.start();
			}
		});
	}
}
3.UI线程中发送消息并在Work线程执行

基本步骤:
1.准备Looper对象
2.生成handler对象
3.Looper.loop()循环取出Message对象

/**
 * Created by magic on 2016年10月23日.UI线程中发送消息 work线程中接收消息
 */
@SuppressLint("HandlerLeak")
public class ThreeActivity extends Activity {

	Button button;
	Handler handler;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		textView = (TextView) findViewById(R.id.tev);
		button = (Button) findViewById(R.id.btn);
		button.setText("UI->Work");
		button.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View arg0) {
				Message message = handler.obtainMessage();
				message.arg1 = 1;
				message.obj = " obj消息";
				// 主线程中发送消息
				handler.sendMessage(message);
				System.out.println(Thread.currentThread().getName());
				// main
			}
		});

		new MyThread().start();
	}

	class MyThread extends Thread {
		@Override
		public void run() {
			// 准备Looper对象
			Looper.prepare();
			handler = new Handler() {
				public void handleMessage(Message msg) {
					System.out.println(Thread.currentThread().getName());
					// Thread-401
					System.out.println("消息->" + msg.what + "-" + msg.obj);
					// 消息->0- obj消息
				};
			};
			// 循环取出消息队列中的消息对象
			Looper.loop();
			super.run();
		}
	}

}

3、Handler post方法的使用

new Handler().post(Runnable r)
new Handler().postAtFrontOfQueue(Runnable r);
new Handler().postAtTime(Runnable r, uptimeMillis);
new Handler().postAtTime(Runnable r, token, uptimeMillis);
new Handler().postDelayed(Runnable r, delayMillis);

Handler执行post方法会将参数Runnable对象,设置成Message的callback属性Message消息对象加入队列,如下:

Handler->post->Message.callback=r->join MessageQueue

该Runnable对象的run方法会在UI线程中执行,当取出Message对象时判断出该Message的callback不为null,于是调用handleCallback(msg)方法,该方法内部执行callback.run()方法。因为未开启新的线程,所以run方法内部不能执行耗时操作。

如有问题恳请指正,谢谢!

END.

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 中,可以使用 Handler 进行进程间通信。以下是使用 Handler 进行进程间通信的基本步骤: 1. 在发送方进程中创建 Handler 对象,并在其构造函数中传递一个 Looper 对象。这个 Looper 对象可以通过调用 Looper.myLooper() 或 Looper.getMainLooper() 方法获取。 2. 在接收方进程中创建一个 Messenger 对象,将其作为参数传递给发送方进程的 Handler 对象的构造函数。 3. 在发送方进程中,通过 Messenger.send() 方法向接收方进程发送消息。在发送消息时,需要创建一个 Message 对象,并将其传递给 Messenger.send() 方法。 4. 在接收方进程中,需要创建一个 Handler 对象,并在其 handleMessage() 方法中处理消息。在创建 Handler 对象时,需要将当前线程的 Looper 对象作为参数传递给其构造函数。 5. 在接收方进程中,通过 Messenger 的 bindService() 方法来连接发送方进程的服务,从而接收发送方进程发来的消息。 下面是一个简单的示例代码,用于演示如何在两个进程之间使用 Handler 进行通信: 在发送方进程中: ``` // 创建 Handler 对象 Handler handler = new Handler(Looper.myLooper()) { @Override public void handleMessage(Message msg) { // 处理接收到的消息 } }; // 创建 Messenger 对象 Messenger messenger = new Messenger(handler); // 发送消息 Message message = Message.obtain(); messenger.send(message); ``` 在接收方进程中: ``` // 创建 Handler 对象 Handler handler = new Handler(Looper.myLooper()) { @Override public void handleMessage(Message msg) { // 处理接收到的消息 } }; // 创建 Messenger 对象 Messenger messenger = new Messenger(handler); // 绑定发送方进程的服务 Intent intent = new Intent(); intent.setComponent(new ComponentName("com.example.sender", "com.example.sender.MyService")); bindService(intent, new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 连接成功,保存 Messenger 对象 messenger = new Messenger(service); } @Override public void onServiceDisconnected(ComponentName name) { // 连接断开 } }, Context.BIND_AUTO_CREATE); ``` 注意:在进行进程间通信时,需要使用 AIDL 接口来定义消息的格式。具体的实现方式超出了本回答的范围,可以查阅相关文档进行学习。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值