Hanlder简介
相比于 AsyncTask,Handler类允许准确的控制操作的运行时间,而且还可以多次使用,执行的操作会一直运行,直到被显示的停止。每个Handler实例都被包含在一个单独的线程里面。
Handler 有两个主要的用途 :
1. 确保一些调度信息和任务在未来的某一时刻被执行
2. 让一些行为在其他的线程中表现出来
HandlerThread 介绍
HandlerThread 类用于创建一个带有 Looper 的新线程,这个Looper可以用于创建Handler 实例,HandlerThread 的实例必须在调用start() 方法后才可以使用。
构造方法 :
1. HandlerThread(String name)
2. HandlerThread (String name, int priority) //priority 就是线程运行的优先级,由 Process类中的变量 来指定
方法 :
1. getLooper ()
这个方法用于获取与该线程相关联的 Looper,如果该线程没有开启,也即未调用 start() 方法,那么这个方法会返回一个 null 值。如果线程已经开启,这个方法会被阻塞直到 Looper 初始化完成。
- getThreadId ()
用于返回线程的标识符
- quit ()
停止线程中的Looper,该方法被调用后,任何对Looper 的请求都会失败。比如,sendMessage(Message) 方法会返回false。使用这个方法可能是不安全的,因为在Looper被终止的时候可能还有 Message 未被递交。
- quitSafely ()
和上一个方法完成的功能相同,不过这个方法更安全,因为在Looper被终止时,一些未递交的 Message 会因为时间的关系不再递交。
- run ()
调用 Runnable 对象中的run() 方法,如果未设置Runnable,就什么也不做。
- onLooperPrepared ()
该方法是 protected 类型的,当我们需要在 Looper 的loop() 方法调用前需要完成一些工作,那么可以复写这个方法。
Looper 的简单介绍
Looper 类用来为线程运行 消息循环,默认的Threads 并不包含一个 message loop,为了创建一个,可以在线程中调用 prepare(),然后调用 loop() 去处理messages
官方给出的示例
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
介绍一下Looper 类中的一些方法
- Looper getMainLooper ()
获得应用程序的主 Looper,存在于主线程中
- Thread getThread ()
返回与该 Looper 关联的 Thread
- void loop ()
在线程中运行 message queue,与此方法对应的是 quit() 方,而且这两个方法必须同时出现。
- Looper myLooper ()
返回与该线程关联的 Looper,如果该线程没有关联 Looper,就返回 null
- MessageQueue myQueue ()
返回与该线程关联的 MessageQueue,如果在未关联 Looper 的线程中调用该方法,会抛出 NullPointerException
- void prepare ()
初始化该线程作为一个Looper
- void quit ()
- void quitSafely()
功能和上面HandlerThread 中介绍的一样
异步消息处理机制
首先,在主线程中创建一个 Handler,并重写 handleMessage() 方法,然后当子线程需要进行 UI 操作时,就创建一个 Message 对象,并通过 Handler 将消息发送出去。之后这条消息会被添加到 MessageQueue 的队列中进行等待,而 Looper 会一直尝试从 MessageQueue 中取出待处理消息,最后分发回 Handler 的 handleMessage() 方法中。由于 Handler 是在主线程中创建的,此时的 handleMessage() 也会在主线程中得到执行。
一个Message 经过一个流程的辗转,从子线程进入到主线程,从不能更新 UI 到可以更新 UI,这就是异步消息处理机制的核心思想。
Hanlder 的简单使用
由于 Handler 中的方法太多,就不逐一介绍了,下面来介绍 几种给 Handler 发送信息的方法。
- Message.obtain(mHanlder,FLAG,data).sendToTarget()
创建一个标识为 FLAG,数据为 data 的Message,立刻将其发送到 Handler 去执行
- mHandler.sendEmptyMessage(FLAG)
立刻给 Handler 发送一个带有标识的空消息
- mHanlder.sendEmptyMessageAtTime(FLAG,1000)
给 Handler 发送一个简单的空消息,该消息会在一秒后被递交给 Looper
- mHandler.sendEmptyMessageDelayed(FLAG,1000)
效果同上
下面利用 Handler 来更改 UI
public class MainActivity extends AppCompatActivity {
public static final int FLAG = 0;
private Button mButton;
private TextView mTextView;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == FLAG) {
mTextView.setText("After Changer");
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = (Button) findViewById(R.id.start);
mTextView = (TextView) findViewById(R.id.tx);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new Thread(new Runnable() {
@Override
public void run() {
mHandler.sendEmptyMessage(FLAG);
}
}).start();
}
});
}
}
注意,这个时候mHandler 使用的是默认 Looper,也即 MainLooper,我们也可以通过 HandlerThread 来使用自己的 Looper执行该操作。
public class MainActivity extends AppCompatActivity implements Handler.Callback {
public static final int FLAG = 0;
private Button mButton;
private TextView mTextView;
private HandlerThread mHandlerThread;
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandlerThread = new HandlerThread("MyHandlerThread");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper(), this);
mButton = (Button) findViewById(R.id.start);
mTextView = (TextView) findViewById(R.id.tx);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new Thread(new Runnable() {
@Override
public void run() {
mHandler.sendEmptyMessage(FLAG);
}
}).start();
}
});
}
@Override
public boolean handleMessage(Message message) {
if (message.what == FLAG) {
mTextView.setText("After Change");
}
return true;
}
}
这个时候会出现一个错误,因为我们自己的 Looper 是没有权限去更新 UI 的,如果想要更新 UI ,可以在 Handler 的构造方法中使用 getMainLooper() 方法。
以上我们都使用使用默认的 mHandler 和 HandlerThread,我们也可以写一个类继承自 HandlerThread 或者 Handler,在自定义的类中可以执行一些耗时任务,因为这个时候所有的任务都是在子线程中执行的,并不会阻塞主线程。
关于 AsyncTask 和 Handler 的选择,如果不是很频繁的执行一个操作,而且操作可以在较短时间内完成,使用 AsyncTask 是十分方便的。如果需要安排操作的时间或者需要快速间隔的执行某操作,Handler 是不错的选择。
本文深入探讨了Android中Handler和Looper的工作原理及应用。详细讲解了Handler如何实现跨线程的消息传递,以及Looper如何循环处理消息队列。同时,还介绍了HandlerThread的使用方法及其与主线程交互的过程。
476

被折叠的 条评论
为什么被折叠?



