首页 > 学院 > 开发设计 > 正文

Thread,Runnable,Handler,HandlerThread探索总结

2019-11-08 00:12:53
字体:
来源:转载
供稿:网友

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轮询的。

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


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表