Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

性能优化十九之多线程优化-HandlerThread、IntentService、Loader简介

$
0
0

前言

       除了AsyncTask之外,Android还提供了其他的一些线程操作来方便开发者使用,接下来进行总结

一、HandlerThread:
       HandlerThread是用来替代Thread的,本身HandlerThread就是继承Thread的,但是与Thread的区别在于,内部有一个Looper成员变量,通过Thread+Looper来实现,实际上就是HandlerThread封装了一个带有自己Looper的线程,可以方便的利用它来处理耗时任务,达到解决一个线程多个异步任务的问题。
       使用案例:

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(); //取消
    }
}

HandlerThread源码分析如下:

public class HandlerThread extends Thread {
    int mPriority;//线程优先级
    int mTid = -1;
    Looper mLooper;//当前线程持有的looper对象

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }

    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }


    protected void onLooperPrepared() {
    }

    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare(); //创建Looper和messageQueue,将looper设置到ThreadLocal中
        synchronized (this) {
            mLooper = Looper.myLooper();//获取到looper对象
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();//开启子线程的消息循环
        mTid = -1;
    }

    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }

        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }

    public boolean quitSafely() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quitSafely();
            return true;
        }
        return false;
    }

    public int getThreadId() {
        return mTid;
    }

重点看getLooper方法,首先会调用isAlive()方法测试线程是否还活着,如果不是,则直接返回null。接着会进入一个同步代码块,当线程还存活着且成员变量mLooper为null时,会执行wait操作,等待run方法中的notifyAll(),由此可知,只要之前我们的HandlerThread被启动了,这个方法会一直阻塞直至mLooper初始化完成,最后将初始化完成的mLooper返回出去。

通常情况下,HandlerThread启动后,会通过getLooper()方法取出Looper对象并将其作为Handler的初始化参数。此时,getLooper()方法是运行在主线程的,而Looper对象的初始化是位于子线程(HandlerThread)的run方法中的,getLooper()方法中的 wait()与run方法中的notifyAll()共同协作,实现了两个线程之间的同步。

总结:
1、HandlerThread本质上是一个Thread对象,只不过其内部帮我们创建了该线程的Looper和MessageQueue;

2、通过HandlerThread我们不但可以实现UI线程与子线程的通信同样也可以实现子线程与子线程之间的通信;

3、HandlerThread在不需要使用的时候需要手动的回收掉;

二、IntentService
       IntentService的本质是Service+HandlerThread+Intent,它是IntentService的子类,可以提高子线程的优先级以及减轻主线程的压力,IntentService可以用来处理耗时操作,因为内部是利用HandlerThread来进行处理的。IntentService内部会创建一个HandlerThread,onHandleIntent在HandlerThread线程中执行

public abstract class IntentService extends Service {
    private volatile Looper mServiceLooper;   //获取当前线程的looper
    private volatile ServiceHandler mServiceHandler; 
    private String mName;  //IntentService名称
    private boolean mRedelivery;

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }

    public IntentService(String name) {
        super();
        mName = name;
    }

    public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

    //可以看到IntentService里封装的就是HandlerThread的实现过程
    @Override
    public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

    @Override
    @Nullable
    public IBinder onBind(Intent intent) {
        return null;
    }

    @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);
}

总结:
       1、启动IntentService类型的Service后,系统通过ServiceHandler将携带的Intent消息放入由HandlerThread线程生成的Looper的消息队列中,Looper依次处理队列中的消息并通过dispatchMessage将消息交给ServiceHandler的Handler来具体执行(其实就是Handler的用法,和我们在Activity中创建Handler并在handleMessage中更新ui的用法一样,只不过这里的handleMessage是在HandlerThread这样的后台线程而不是ui线程中执行的)
       2、调用子类的onHandleIntent方法(用来执行费时操作),结束后关闭Service 总之,这种机制通常用于希望按顺序执行(串行)而非并发(并行)执行的费时操作,
其中每个任务执行完毕的时间是未知的的应用场景。如果希望在任务结束后通知前台可以通过sendBroadCast的方式发送广播。

三、Loader机制
       关于Loader机制,目前自己研究的还不是很深,建议可以看这篇博客:
http://blog.csdn.net/sk719887916/article/details/51540610

作者:hpc19950723 发表于2017/4/25 17:24:42 原文链接
阅读:45 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>