“Can’t create handler inside thread that has not called Looper.prepare()”);
}
这里是通过Looper中的myLooper方法来获得Looper实例的,如果Looper为null的话就会抛异常,抛出的异常内容翻译过来就是
无法在未调用Looper.prepare()的线程内创建handler
从这句话中,我们可以知道,在调用Looper.myLooper()之前必须要先调用Looper.prepare()方法,现在来看下prepare方法中的内容,如下
/** Initialize the current thread as a looper.
-
This gives you a chance to create handlers that then reference
-
this looper, before actually starting the loop. Be sure to call
-
{@link #loop()} after calling this method, and end it by calling
-
{@link #quit()}.
*/
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()方法调用了prepare(boolean quitAllowed)方法,prepare(boolean quitAllowed) 方法中则是实例化了一个Looper,然后将Looper设置进sThreadLocal中,到了这里就有必要了解一下ThreadLocalle。
什么是ThreadLocal
ThreadLocal 为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。
当使用ThreadLocal 维护变量时,ThreadLocal 为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
如果看完上面这段话还是搞不明白ThreadLocal有什么用,那么可以看下下面代码运行的结果,相信看下结果你就会明白ThreadLocal有什么作用了。
public class MainActivity extends AppCompatActivity {
private static final String TAG = “MainActivity”;
private ThreadLocal mThreadLocal = new ThreadLocal<>();
@SuppressLint(“HandlerLeak”)
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 1) {
Log.d(TAG, "onCreate: "+mThreadLocal.get());
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mThreadLocal.set(5);
Thread1 thread1 = new Thread1();
thread1.start();
Thread2 thread2 = new Thread2();
thread2.start();
Thread3 thread3 = new Thread3();
thread3.start();
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
mHandler.sendEmptyMessage(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
class Thread1 extends Thread {
@Override
public void run() {
super.run();
mThreadLocal.set(1);
Log.d(TAG, "mThreadLocal1: "+ mThreadLocal.get());
}
}
class Thread2 extends Thread {
@Override
public void run() {
super.run();
mThreadLocal.set(2);
Log.d(TAG, "mThreadLocal2: "+ mThreadLocal.get());
}
}
class Thread3 extends Thread {
@Override
public void run() {
super.run();
mThreadLocal.set(3);
Log.d(TAG, "mThreadLocal3: "+ mThreadLocal.get());
}
}
}
看下这段代码运行之后打印的log