Handler的用法
/**
* 1、Handler内存泄露测试
* 2、为什么不能在子线程创建Handler
* 3、textView.setText()只能在主线程执行,这句话是错误!
* 4、new Handler()两种写法有什么区别?
* 5、ThreadLocal用法和原理
*/
public class MainActivity extends AppCompatActivity {
private TextView textView;
private Message message;
// 4、new Handler()两种写法有什么区别?
private Handler handler1 = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
startActivity(new Intent(MainActivity.this, PersonalActivity.class));
return false;
}
});
// 这是谷歌备胎的api,不推荐使用
private Handler handler2 = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
textView.setText(msg.obj.toString());
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.tv);
message = new Message();
test();
}
private void test() {
new Thread(new Runnable() {
@Override
public void run() {
// 常规的写法
// message.obj = "Net163";
// message.what = 163;
// handler2.sendMessage(message);
// 1、Handler内存泄露测试(假象)
SystemClock.sleep(1000); // 销毁Activity
// message.what = 3;
// This message is already in use.
// if (handler1 != null) handler1.sendMessage(message); // 跳转到第二个界面
// handler1.sendMessageDelayed(message, 3000);
// 2、为什么不能在子线程创建Handler
// new Handler();
// 3、textView.setText()只能在主线程执行,这句话是错误!
// textView.setText("彭老师");
Toast.makeText(MainActivity.this, "彭老师", Toast.LENGTH_SHORT).show();
}
}).start();
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.e("netease >>> ", "onDestroy");
// 不推荐写法
message.recycle();
handler1.removeMessages(3);
handler1 = null;
}
}
Handler原码流程解析
Handler手写原码实现 模拟过程
public class ActivityThread {
@Test
public void main() {
// 创建全局唯一的,主线程Looper对象,以及MessageQueue消息队列对象
Looper.prepare();
// 模拟Activity中,创建Handler对象
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
System.out.println(msg.obj.toString());
}
};
// 消费消息,回调方法(接口方法)
// 子线程发送消息
new Thread(new Runnable() {
@Override
public void run() {
Message message = new Message();
message.obj = "hello net163";
handler.sendMessage(message);
}
}).start();
// 轮询,取出消息
Looper.loop();
}
}
public class Looper {
public MessageQueue mQueue;
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private Looper() {
mQueue = new MessageQueue();
}
public static void prepare() {
// 主线程只有唯一一个Looper对象
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 应用启动时,初始化赋值
sThreadLocal.set(new Looper());
}
//
public static Looper myLooper() {
return sThreadLocal.get();
}
// 轮询,提取消息
public static void loop() {
// 从全局ThreadLocalMap中获取唯一:Looper对象
Looper me = myLooper();
// 从Looper对象中获取全局唯一消息队列MessageQueue对象
final MessageQueue queue = me.mQueue;
Message resultMessage;
// 从消息队列中取消息
while (true) {
Message msg = queue.next();
if (msg != null) {
if (msg.target != null) msg.target.dispatchMessage(msg);
}
}
}
}
package com.snow.core;
public class Handler {
private Looper mLooper;
private MessageQueue mQueue;
public Handler() {
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
}
public void sendMessage(Message message) {
// 将消息放入消息队列中
enqueueMessage(message);
}
private void enqueueMessage(Message message) {
// 赋值当前handler
message.target = this;
// 使用mQueue,将消息放入
mQueue.enqueueMessage(message);
}
public void dispatchMessage(Message msg) {
handleMessage(msg);
}
// 给开发者提供的开放API,用于重写和回调监听
public void handleMessage(Message msg) {
}
}
// 消息对象
public class Message {
// 标识
public int what;
// Handler对象
public Handler target;
// 消息内容
public Object obj;
public Message() {
}
public Message(Object obj) {
this.obj = obj;
}
// 模拟
@Override
public String toString() {
return obj.toString();
}
}
// 消息队列
public class MessageQueue {
// 阻塞队列
BlockingQueue<Message> blockingQueue = new ArrayBlockingQueue<>(50);
// 将Message消息对象存入阻塞队列中
public void enqueueMessage(Message message) {
try {
blockingQueue.put(message);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 从消息队列中取出消息
public Message next() {
try {
return blockingQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}