Thread,Runnable,Handler,HandlerThread探索总结

来源:互联网 发布:为什么淘宝价格低 编辑:程序博客网 时间:2024/04/19 17:35

Thread,Runnable,Handler,Handler.Callback,Looper,MessageQueue,HandlerThread

新线程的开启:

new Thread(new Runnable() {    @Override    public void run(){        //异步执行    }}).start();②class MyThread extends Thread {    @Override    public void run(){        //异步执行    }}new MyThread().start();③class MyRunnable implements Runnable {    @Overrid    public void run(){        //异步执行    }}new Thread(new MyRunnable()).start();

Runnable:
Runnable

按抠脚的英语理解的是,Runnable接口被实现后,必须要用Thread类开启线程,Runnable的设计理念是提供一个公共的方法执行内容。Runnable不一定要用new Thread()的方法来实例化Runnable,也可以用继承Thread来重写run()方法。

Handler

class MyThread extends Thread {    private Handler myHandler;    @Override    public void run() {        Looper.prepare();//要在线程中实例化Handler,就必须调用该方法        myHandler = new Handler();        //异步执行        //在最后还要执行Looper.loop();不然消息是不会发送到消息队列中的        myHandler.post(new Runnbale() {            @Overrid            public void run(){                //属于异步线程            }        });    }}②Handler handler = new Handler(){...};class MyThread = new Thread(){...}

这时候其实挺疑惑为什么在Thread中一定要调用Looper.prepare();可以先看下构造函数,然后看看源码。
Handler构造函数
Handler.Callback是可以重写Handler类中的handlerMessage()方法。
可知道只要是不传Looper对象的构造参数,
没有参数的Handler构造函数

传Callback的Handler构造函数
最终都是走到以下这个方法:

public Handler(Callback callback, boolean async) {        if (FIND_POTENTIAL_LEAKS) {            final Class<? extends Handler> klass = getClass();            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) {                Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName());            }        }        mLooper = Looper.myLooper();        if (mLooper == null) {            throw new RuntimeException("Can't create handler inside thread that has not called Looper.prepare()");        }        mQueue = mLooper.mQueue;        mCallback = callback;        mAsynchronous = async;    }

在这行中mLooper = Looper.myLooper()中,可以看到看到,当mLooper==null的时候,会报当前线程没有调用Looper.prepare(),而在Looper.prepare,Looper.prepare()中看下面:

public static @Nullable Looper myLooper() {        return sThreadLocal.get(); // 获取线程Looper}public static void prepare() {        prepare(true);    }private static void prepare(boolean quitAllowed) {        if (sThreadLocal.get() != null) {            throw new RuntimeException("Only one Looper may be created per thread");        }        sThreadLocal.set(new Looper(quitAllowed)); // prepare是会实例化一个新的Looper    }

从以上就知道为什么要调用Looper.prepare()了。而在Activity中的实例化Handler却不需要的原因的是在ActivityThread中已经调用了Looper.prepareMainLooper();
所以这里要注意的地方就是,在Thread中实例化的Handler是不能修改UI线程了。因为它的消息队列被异步线程的Looper轮询了,而不是MainLooper轮询的。看了Handler.post()和View.post()的代码就知道为什么不行了。

// Handler.post只是调用的sendMessageDelayed.其调用的是异步线程的消息队列public final boolean post(Runnable r){    return  sendMessageDelayed(getPostMessage(r), 0);}//--- 分割线 ---public boolean post(Runnable action) {   final AttachInfo attachInfo = mAttachInfo;   if (attachInfo != null) {       return attachInfo.mHandler.post(action);   }   // Assume that post will succeed later   ViewRootImpl.getRunQueue().post(action);   return true;}/**  * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This  * handler can be used to pump events in the UI events queue.  */final Handler mHandler;

而AttachInfo看源码注释就是A set of information given to a view when it is attached to its parent window.获取的其父类窗口的一些属性。mHandler其实就是父类MainThread的消息队列的Handler。

HandlerThread:

HandlerThread handlerThread = new HandlerThread("myHandlerThread");handlerThread.start();Handler asyncHandler = new Handler(handlerThread.getLooper());Handler uiHandler = new Handler();asyncHandler.post(new Runnable(){    @Override    public void run(){        // 异步        uiHandler.post(new Runnbale(){            // ui线程        })    }});/*HandlerThread开启的线程后。声明asyncHandler的时候将HandlerThread的Looper赋给asyncHandler,那么asyncHandler post的就是一个异步的的Runnable.而uiHandler没有的到HandlerLooper,所以是MainActivity的Looper,属于Ui线程。*/②Handler uiHandler = new Handler() {    @Override    public void handleMessage() {...}}asyncHandler.post(new Runnable(){    @Override    public void run(){        // 异步        uiHandler.sendMessage(...);    }});

Android提供的在其它线程操作UI线程的方法:

①Activity.runOnUiThread(Runnable)②View.post(Runnable)③View.postDelayed(Runnable, long)

相关查阅资料:
http://blog.csdn.net/guolin_blog/article/details/9991569
https://developer.android.com/reference/android/os/Handler.html
https://developer.android.com/reference/java/lang/Runnable.html
https://developer.android.com/reference/java/lang/Thread.html
https://developer.android.com/reference/android/os/Looper.html
在其它线程访问UI线程:
https://developer.android.com/guide/components/processes-and-threads.html
https://developer.android.com/training/multiple-threads/communicate-ui.html#Handler

0 0