Android性能优化

android 多线程优化 --- Handler,Handle

2017-10-26  本文已影响0人  田间小鹿

1.handler

1.1 handler执行流程

Handler是线程与线程间进行通信的一套机制.

一个Android应用程序被创建时就会创建一个进程,该进程用应用的包名作为进程名。该进程会启动主线程ActivityThread,也叫做UI主线程,但有时需要做些耗时操作,为了不去阻塞UI主线程的正常运行,我们将它放在子线程中进行操作,操作完成后需要绘制UI,但Android子线程不能直接操作UI线程的,所以通过Handler来进行通信。
handler流程
  1. 当一个应用创建的时候就会进入到UI线程ActivityThread。然后执行当中的mian()入口函数。
  2. 在main函数中会同prepareMainLooper来创建一个主线程Looper。在looper中会创建出一个sThreadLocal用来保存Looper副本,并把looper和当前的线程绑定。通过set和get的方法设值。
  3. Looper调用prepare函数来set,sThreadlocal,并创建一个MessagQueue消息队列。
不能在主线程中重复调用
我们在项目中不能直接调用prepareMainLooper() 不能在子线程中调用

也不能在子线程中调用。

  1. 对于系统的Handler系统中定义了一系列消息发在H中。比如:启动activity,绑定service等我们只有在需要的时候发送消息就可以了。Handler也可以自定义。并可以通过sendMessage或者post去把消息放入MessageQueue中。
  2. 然后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,然后就只需要等待任务执行结束的时候通知返回到主线程就好了。

关键:

  1. 内部有一个Handler。
  2. 实现了将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");
    }

}
执行流程
上一篇 下一篇

猜你喜欢

热点阅读