Android Handler使用详解

        handler是android给我们提供用来更新UI的一套机制,也是一套消息处理的机制,我们可以发送消息,也可以通过它处理消息。

        它最根本的目的就是解决多线程并发问题,假设如果在一个Activity当中,有多个线程去更新UI,并且都没有加锁机制,就会产生更新界面错乱。如果对更新UI的操作都进行枷锁处理又会使应用性能下降,所以Android给我们提供了一套更新UI的机制,我们只需要遵循这样的机制就可以了,根本不用去关心多线程问题,多有的更新UI操作,都是在主线程的消息队列当中去轮询处理的。

handler的使用:

1、使用handler更新UI

详细参考:Android Handler使用详解之UI更新

定义handler

private Handler handler = new Handler();

定义Runnable

Runnable runnable = new Runnable() {
	public void run() {
		tetxView.setText("cx");
	}
};

启动Runnable

handler.post(runnable);

2、使用handler延时更新UI

前面相同,只有启动时有差别

handler.postDelayed(runnable, 2000);//延时2s更新UI

延时发送通知

handler.sendEmptyMessageDelayed(what, 2000);

3、使用handler消息传递

创建消息,可以创建不同类型的消息(这里arg1、arg2和obj)

Message message = new Message(); //或Message message = handler.obtainMessage();这是也可以用message.sendToTarget();发送消息
message.arg1=66;
message.arg2=33;
message.obj="cx";
handler.sendMessage(message);

接收并处理消息

private Handler handler = new Handler(){
	public void handleMessage(Message msg) {
		tetxView.setText((String) msg.obj + msg.arg1 + msg.arg2);
	};
};

4、消息延时传递sendMessageDelayed,与上面相同。

5、handler移除功能

例如:在2中的延时更新UI过程中,在延时过程中移除,则UI不再更新。

handler.removeCallbacks(runnable);

6、handler消息拦截

消息接收

private Handler handler = new Handler(new Callback() {
		
	@Override
	public boolean handleMessage(Message msg) {
		// TODO Auto-generated method stub
		Toast.makeText(getApplicationContext(), "1", 1).show();
		return true;//返回false,执行完上面的代码在执行下面的;返回true,则不再执行下面的代码
	}
}){
	@Override
	public void handleMessage(Message msg) {
		// TODO Auto-generated method stub
		Toast.makeText(getApplicationContext(), "2", 1).show();
	}
};

发送一个空消息

handler.sendEmptyMessage(1);

7、handler原理总结:

Handler负责发送消息,Looper负责接收Handler发送的消息,并直接把消息回传给handler自己,MessageQueue就是一个存储消息的容器。

8、创建与子线程相关的Handler

主线程的Handler中不要执行耗时操作,否则界面会出现卡死现象。

创建主线程Handler

private Handler handler = new Handler(){
	public void handleMessage(android.os.Message msg) {
		System.out.println("UI-----------"+Thread.currentThread());
	};
};

创建子线程和子线程Handler

class MyThread extends Thread{
	public Handler handler;
	@Override
	public void run() {
		// TODO Auto-generated method stub
		Looper.prepare();//要创建handler必须先创建接收handler消息的Looper
		handler=new Handler(){
			public void handleMessage(android.os.Message msg) {
				System.out.println("-----------"+Thread.currentThread());
			};
		};
		Looper.loop();//开始循环Looper
	}
};

发送消息

MyThread thread=new MyThread();//定义子线程
thread.start();//启动子线程
thread.handler.sendEmptyMessage(1);//向子线程Handler发送消息
handler.sendEmptyMessage(1);<span style="font-family: Arial, Helvetica, sans-serif;">//向主线程Handler发送消息</span>

9、HandlerThread

在主线程的Handler中传入子线程中定义的Looper时,会出现空指针问题。

定义子线程及子线程中的Handler和Looper

class MyThread extends Thread{
	public Handler handler;
	public Looper looper;
	@Override
	public void run() {
		// TODO Auto-generated method stub
		Looper.prepare();
		looper=Looper.myLooper();
		handler=new Handler(){
			public void handleMessage(android.os.Message msg) {
				System.out.println("-----------"+Thread.currentThread());
			};
		};
		Looper.loop();
	}
};

启动子线程,创建一个Handler并传入子线程中的Looper

MyThread thread=new MyThread();
thread.start();
Handler handler=new Handler(thread.looper){
	public void handleMessage(android.os.Message msg) {
		System.out.println(msg);
	};
};

        运行程序会出现错误,thread.looper为空,因为在主线程中创建Handler时,子线程中的Looper还没有创建,这就是多线程并发的问题。修改上面代码:

HandlerThread thread=new HandlerThread("chenxu");//主要功能就是创建Looper,参数为线程名。
thread.start();
Handler handler=new Handler(thread.getLooper()){
	public void handleMessage(android.os.Message msg) {
		//可执行耗时操作
		System.out.println(">>>>>>>>>>>>" + Thread.currentThread());//与上面线程名一致
	};
};
handler.sendEmptyMessage(1);

        这时的handler就相当于是子线程中的handler,即使执行耗时操作也不会出现界面卡顿的现象。

10、主线程与子线程信息交互

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;

public class MainActivity extends Activity {
	private Handler threadHandler;
	
	//主线程handler
	Handler handler = new Handler(){
		public void handleMessage(android.os.Message msg) {
			Message message = new Message();
			//向子线程发送消息
			threadHandler.sendMessageDelayed(message, 1000);
			System.out.println("main handler");
		};
	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		
		HandlerThread thread = new HandlerThread("threadHandler");//主要功能就是创建Looper,参数为线程名。
		thread.start();
		//子线程handler
		threadHandler = new Handler(thread.getLooper()){
			public void handleMessage(android.os.Message msg) {
				Message message = new Message();
				//向主线程发送消息
				handler.sendMessageDelayed(message, 1000);
				System.out.println("threadHandler handler");
			};
		};
		handler.sendEmptyMessage(1);
	}
}

11、其他消息传递方法

发送消息

handler.obtainMessage(1,true).sendToTarget();
handler.obtainMessage(2,"str").sendToTarget();

接收消息

Handler handler = new Handler() {

	@Override
	public void handleMessage(Message msg) {
		super.handleMessage(msg);
			switch (msg.what) {
				case 1:
					boolean b = (Boolean)msg.obj;
				break;
				
				case 2:
					String  s = (String)msg.obj;
			break;
		}
	}
};

12、Handler黄色警告

        出现黄色警告是因为 Handler 在 Android 中用于消息的发送与异步处理,常常在 Activity 中作为一个匿名内部类来定义,此时 Handler 会隐式地持有一个外部类对象(通常是一个 Activity)的引用。当 Activity 已经被用户关闭时,由于 Handler 持有 Activity 的引用造成 Activity 无法被 GC 回收,这样容易造成内存泄露。

        解决办法:将其定义成一个静态内部类(此时不会持有外部类对象的引用),在构造方法中传入 Activity 并对 Activity 对象增加一个弱引用,这样 Activity 被用户关闭之后,即便异步消息还未处理完毕,Activity 也能够被 GC 回收,从而避免了内存泄露。

private MyHandler mHandler = new MyHandler((Activity) context);

// 发送消息
Message message = new Message();
message.what = 1;
mHandler.sendMessage(message);

// 静态内部类
static class MyHandler extends Handler {
    // 弱引用
    WeakReference weakReference;
    public MyHandler(Activity activity) {
        weakReference = new WeakReference(activity);
    }

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case 1:
                Toast.makeText((Context) weakReference.get(), "收到消息", Toast.LENGTH_SHORT).show();
                break;
            default:
                // do something...
                break;
        }
    }
}

13、消息队列使用

private ExecutorService singleThreadExecutor = null;
private LinkedBlockingQueue linkedBlockingQueue = new LinkedBlockingQueue<Runnable>(200);

/**
 * 创建队列
 */
private ExecutorService getThreadExecutor() {
    if (singleThreadExecutor == null) {
        singleThreadExecutor = new ThreadPoolExecutor(1, 1,
                1000L, TimeUnit.MILLISECONDS,
                linkedBlockingQueue);
    }
    return singleThreadExecutor;
}

/**
 * 加入队列
 */
getThreadExecutor().execute(new Runnable() {
        @Override
        public void run() {
            //要执行的代码
        }
    });
}
  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Handler机制是Android中用于实现线程间通信的一种机制。它的主要原理是通过消息队列(MessageQueue)和消息循环(Looper)来实现。 在Android中,每个线程都有一个消息队列,用于存放待处理的消息。当线程需要发送消息时,可以通过Handler将消息发送到目标线程的消息队列中。由于每个线程都有自己的消息队列,因此可以实现不同线程之间的通信。 消息队列中的消息会按照先进先出的顺序被处理。当目标线程处于空闲状态时,它会不断地从消息队列中取出消息,并通过Handler的回调方法(Callback)对消息进行处理。处理完一个消息后,它会继续处理下一个消息,直到消息队列为空。 消息循环是实现消息队列轮询的一种机制。它会不断地从消息队列中取出消息,并将消息交给对应的Handler进行处理。当消息队列为空时,消息循环会进入休眠状态,等待新的消息到来。 通过Handler机制,我们可以在不同线程之间发送消息,实现线程之间的通信和任务的调度。它在Android开发中经常被用于更新UI、处理耗时操作等场景。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Handler原理解析(图文详解)](https://blog.csdn.net/haovin/article/details/89609688)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [AndroidHandler机制实现原理分析](https://download.csdn.net/download/weixin_38719890/15470797)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [android Handler机制原理解析(一篇就够,包你形象而深刻)](https://blog.csdn.net/luoyingxing/article/details/86500542)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

c小旭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值