Handler(原理)创建一个与线程相关的Handler
来源:互联网 发布:参与网络博客是否违法 编辑:程序博客网 时间:2024/05/22 16:51
我们通常在Activity中创建的Handler,是与UI线程绑定的,这里说的绑定其实是指,Looper和MessageQueue的绑定,
而这里的线程,也就是Looper和MessageQueue所在的线程,也就是说Handler所持有的Looper和MessageQueue是
哪个线程的,我们就说,此Handler是与哪个线程绑定的。
下面先看一个例子
package com.example.liaoli.handler_demo;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;public class MainActivity extends AppCompatActivity { private static final String TAG = "Handler_demo"; private Handler UIHandler = new Handler(){ @Override public void handleMessage(Message msg) { Log.e(TAG, "UI线程:" + Thread.currentThread()); } }; class MyThread extends Thread { public Handler handler ; public Looper looper; public void run(){ Looper.prepare(); looper = Looper.myLooper(); handler = new Handler(){ @Override public void handleMessage(Message msg) { Log.e(TAG,"当前线程:" + Thread.currentThread()); } }; Looper.loop(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MyThread mt = new MyThread(); mt.start(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } mt.handler.sendEmptyMessage(0); UIHandler.sendEmptyMessage(0); }}
运行之后打印的结果是:
09-26 18:10:32.072 30495-30507/com.example.liaoli.handler_demo E/Handler_demo﹕ 当前线程:Thread[Thread-170,5,main]
09-26 18:10:32.080 30495-30495/com.example.liaoli.handler_demo E/Handler_demo﹕ UI线程:Thread[main,5,main]
以上结果说明
@Override public void handleMessage(Message msg) { Log.e(TAG,"当前线程:" + Thread.currentThread()); }中的代码是运行在子线程中的,此时我们其实就是创建了一个与子线程绑定的Handler实例。
子线程的run方法中的
looper = Looper.myLooper();
其实就是在创建一个本子线程的Looper 实例,而在创建Looper的时候又会创建MessageQueue,
然后在handler的构造方法中会拿到这两个实例,从而建立绑定关系。看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;}
再看Looper的myLooper()方法
/** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */public static @Nullable Looper myLooper() { return sThreadLocal.get();}
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));}
sThreadLocal
是ThreadLocal类的一个实例,Threadlocal类的作用就是,来实现线程的数据共享与分离,这里的共享指的是同一个线程间的共享,分离指的是不同线程件的分离,我们可以将其理解
成一个Map,这个Map的key是我们的线程实例,value就是我们存的与此线程相关的值,当然
ThreadLocal存取并不需要指定Key,只需要用
public T get()和
public void set(T value)方法来取和存数据,当然必须得先存了在能取到数据。
ThreadLocal会根据线程去取或存这个值。也就是说只有同一个线程中取出来的值才是同一个值,
其实,简单理解成Map就好。
这也就能解释为什么我们在通常我们在Activity中创建用来更新UI的界面为什么会运行在UI线程中的问题。
这就是因为为我们创建的Handler是与ActivityThread的UI线程中Looper绑定的
ActivityThread的main方法中的代码片段:
Looper.prepareMainLooper();
……
……
Looper.loop();
这就在主(UI)线程中,创建了一个Looper,然后我们在Activity(UI线程中)中创建了一个Handler,Handler 在构造函数中
就会和这个主线程中的Looper绑定。所以此时Handler的
private Handler UIHandler = new Handler(){ @Override public void handleMessage(Message msg) { Log.e(TAG, "UI线程:" + Thread.currentThread()); } };
的
public void handleMessage(Message msg)
中的代码是运行在UI线程中的。
再看
public class MainActivity extends AppCompatActivity { private static final String TAG = "Handler_demo"; private Handler myHandler; class MyThread extends Thread { public Handler handler ; public Looper looper; public void run(){ Looper.prepare(); looper = Looper.myLooper(); handler = new Handler(){ @Override public void handleMessage(Message msg) { Log.e(TAG,"当前线程:" + Thread.currentThread()); } }; Looper.loop(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MyThread mt = new MyThread(); mt.start(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } mt.handler.sendEmptyMessage(0); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } myHandler = new Handler(mt.looper){ @Override public void handleMessage(Message msg) { Log.e(TAG, "Run IN 线程:" + Thread.currentThread()); } }; myHandler.sendEmptyMessage(0); }}
运行结果
09-26 18:18:44.784 1931-1943/com.example.liaoli.handler_demo E/Handler_demo﹕ 当前线程:Thread[Thread-176,5,main]
09-26 18:18:46.784 1931-1943/com.example.liaoli.handler_demo E/Handler_demo﹕ Run IN 线程:Thread[Thread-176,5,main]
发型这两个Handler的Handler的
public void handleMessage(Message msg)方法的代码是运行在同一个线程的,
也就是说 Looper是哪个线程的,与之绑定的Handler的
public void handleMessage(Message msg)方法就运行与哪个线程。
- Handler(原理)创建一个与线程相关的Handler
- 面试常客Handler详细解析(自定义与线程相关的Handler)(三)
- 线程阻塞与Handler相关超详细原理讲解
- Handler与线程的关系
- Handler的使用与原理
- android线程 handler原理
- 子线程创建Handler
- Handler实现线程间通信的原理
- Handler处理线程间通讯的原理
- 新线程中创建Handler的方法
- android handler创建的简单原理
- Android开发之handler(三)handler真的是重新启动一个线程吗?
- Android开发之handler(三)handler真的是重新启动一个线程吗?
- handler 与线程
- 线程与Handler(1)
- android handler与线程
- handler.post 与线程
- 安卓开发线程与线程的通信-handler机制的原理
- Java复选框JCheckBox和单选按钮JRadioButton用法详解
- uva 11210 Chinese Mahjong 中国麻将 dfs回溯
- Google Java编程风格指南
- 辞职二战一个月感想
- 快乐的sublime编辑器(笔记)
- Handler(原理)创建一个与线程相关的Handler
- SNMP简单网络管理协议
- 启动另一个Activity
- Boost ASIO攻破!!!(★firecat推荐★)
- Essential C++学习笔记系列-第一章
- android 6.0(api 23) SDK,不再提供org.apache.http.*(只保留几个类). 用xUtils会出现问题
- C++11中的std::function
- USACO 1.5 Checker Challenge (DFS)
- poj 3345 树形dp(收买国家)