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接口被实现后,必须要用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.Callback是可以重写Handler类中的handlerMessage()方法。
可知道只要是不传Looper对象的构造参数,
最终都是走到以下这个方法:
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
- Thread,Runnable,Handler,HandlerThread探索总结
- Android中Handler Thread(HandlerThread) Runnable之间的关系
- 安卓线程相关 HandlerThread Handler Thread Looper Message Runnable
- HandlerThread、Handler 、Runnable
- Android Thread,Handler,Loop,Message,HandlerThread总结
- HandlerThread,Handler,Thread使用方法
- HandlerThread,Handler,Thread使用方法
- HandlerThread,Handler,Thread使用方法
- HandlerThread,Handler,Thread使用方法
- HandlerThread,Handler,Thread使用方法
- HandlerThread,Handler,Thread使用方法
- HandlerThread,Handler,Thread使用方法
- Thread、Handler与HandlerThread
- Handler, thread, handlerthread
- HandlerThread,Handler,Thread使用方法
- HandlerThread,Handler,Thread使用方法
- HandlerThread,Handler,Thread使用方法
- Thread,Handler,HandlerThread区别
- 在SpringBoot中使用 拦截器
- 浏览器兼容问题及解决办法
- JS——prototype、闭包、跨域
- MYSQL批量插入千万级数据只需百秒
- 欢迎使用CSDN-markdown编辑器
- Thread,Runnable,Handler,HandlerThread探索总结
- Hadoop中两表JOIN的处理方法
- 较简单的修改和添加功能(链接数据库)
- 豌豆荚排行榜爬取(selenium)
- android通知栏(Notification)的使用
- spring+kaptcha-2.3.2jar图片验证码
- 2-23 学习备忘 GIT以及FLASK初识
- qt 创建共享内存举例
- 1299: [LLH邀请赛]巧克力棒