android 多线程优化 --- Handler,Handle
2017-10-26 本文已影响0人
田间小鹿
1.handler
1.1 handler执行流程
Handler是线程与线程间进行通信的一套机制.
一个Android应用程序被创建时就会创建一个进程,该进程用应用的包名作为进程名。该进程会启动主线程ActivityThread,也叫做UI主线程,但有时需要做些耗时操作,为了不去阻塞UI主线程的正常运行,我们将它放在子线程中进行操作,操作完成后需要绘制UI,但Android子线程不能直接操作UI线程的,所以通过Handler来进行通信。
handler流程
- 当一个应用创建的时候就会进入到UI线程ActivityThread。然后执行当中的mian()入口函数。
- 在main函数中会同prepareMainLooper来创建一个主线程Looper。在looper中会创建出一个sThreadLocal用来保存Looper副本,并把looper和当前的线程绑定。通过set和get的方法设值。
- Looper调用prepare函数来set,sThreadlocal,并创建一个MessagQueue消息队列。
我们在项目中不能直接调用prepareMainLooper() 不能在子线程中调用
也不能在子线程中调用。
- 对于系统的Handler系统中定义了一系列消息发在H中。比如:启动activity,绑定service等我们只有在需要的时候发送消息就可以了。Handler也可以自定义。并可以通过sendMessage或者post去把消息放入MessageQueue中。
- 然后ActivityThread会调用loop函数去循环,去获得消息队列中的消息,并调用消息创建时绑定的handler去调用dispatchMessage,然后去调用具体的handleMessage。
1.2 handler在子线程中运行
官方给出的例子是:
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();
}
}
如果我们要在使用的地方比较多,这样写就会比较繁琐。android为我们提供了一个更好的工具类HandlerThread。
2. HnadlerThread
因为HandlerThread拥有自己的消息队列,它不会干扰或阻塞UI线程,比较合适处理那些需要花费时间偏长的任务。我们只需要把任务发送给HandlerThread,然后就只需要等待任务执行结束的时候通知返回到主线程就好了。
关键:
- 内部有一个Handler。
- 实现了将loop转到子线程中处理
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
一个实际例子
public class HandlerThreadActivity1 extends Activity {
HandlerThread fetchThread = new HandlerThread("fetching_thread");
Handler fetchHandler;
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_thread);
tv = (TextView) findViewById(R.id.tv);
//启动线程
fetchThread.start();
//通过fetchHandler发送的消息,会被fetchThread线程创建的轮询器拉取到
fetchHandler = new Handler(fetchThread.getLooper()){
@Override
public void handleMessage(Message msg) {
//模拟访问网络延迟
SystemClock.sleep(1000);
runOnUiThread(new Runnable() {
@Override
public void run() {
tv.setText("汇率:"+new Random().nextInt(10));
}
});
//循环执行
fetchHandler.sendEmptyMessage(1);
}
};
}
@Override
protected void onResume() {
super.onResume();
fetchHandler.sendEmptyMessage(1);
}
@Override
protected void onStop() {
super.onStop();
fetchThread.quit(); //取消
}
}
3. IntentService
开发中,凡是遇到耗时的操作尽可能的会交给Service去做,比如我们上传多张图,上传的过程用户可能将应用置于后台,然后干别的去了,我们的Activity就很可能会被杀死,所以可以考虑将上传操作交给Service去做,如果担心Service被杀,还能通过设置startForeground(int, Notification)方法提升其优先级。
那么,在Service里面我们肯定不能直接进行耗时操作,一般都需要去开启子线程去做一些事情,自己去管理Service的生命周期以及子线程并非是个优雅的做法;好在Android给我们提供了一个类,叫做IntentService
IntentService是一个基于Service的一个类,用来处理异步的请求。你可以通过startService(Intent)来提交请求,该Service会在需要的时候创建,当完成所有的任务以后自己关闭,且请求是在工作线程处理的。
本质Service+HandlerThread+Intent
优点
(1)不需要自己去new Thread,不需要考虑在什么时候关闭该Service;
(2)提高子线程的优先级;
(3)减轻主线程的压力。
实例:
public class MyIntentService extends IntentService {
//至少要有一个空的构造方法
public MyIntentService() {
super("MyIntentService");
}
public MyIntentService(String name) {
super(name);
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.d("Txb", Thread.currentThread().getName() + "_onStart");
}
//UI线程发送Intent,会在子线程中执行
@Override
protected void onHandleIntent(Intent intent) {
Log.d("Txb", Thread.currentThread().getName() + "_onHandleIntent");
}
}
执行流程