文章参考:书籍 android开发艺术探索
博客:https://www.jianshu.com/p/e172a2d58905
https://blog.csdn.net/qian520ao/article/details/78262289
前言
Android的消息机制主要指的就是Handler的运行机制,handler常被我们用来进行ui的修改。简单的说就是在子线程进行耗时操作,然后通过handler修改ui。
本文将从下面的几个方面来学习handler
基本的使用
要使用Handler我们需要创建一个Handler对象,同时为了能够处理我们自己发送的消息需要重写handleMessage方法。使用handlerf发送消息有两种方式 Handler.sendMessage() 和 Hanler.post()
下面我们就来看看handler的基本使用demo
public class HandlerDemoActivity extends AppCompatActivity {
private final String TAG = getClass().getSimpleName();
//继承Handler重写handleMessage方法处理自己的消息
class MyHandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage( msg );
Log.d( TAG,"接收到消息,可以更新ui" );
}
}
Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_handler_demo );
handler = new MyHandler();
new Thread( new Runnable() {
@Override
public void run() {
try {
Thread.sleep( 3000 );
} catch (InterruptedException e) {
e.printStackTrace();
}
Message message = handler.obtainMessage( 1 );
//使用sendMessage
handler.sendMessage( message );
}
} ).start();
new Thread( new Runnable() {
@Override
public void run() {
try {
Thread.sleep( 3000 );
} catch (InterruptedException e) {
e.printStackTrace();
}
//使用post
handler.post( new Runnable() {
@Override
public void run() {
Log.d( TAG,"Runnable 执行,可以更新ui" );
}
} );
}
} ).start();
}
}
上面的demo就是Handler的基本使用。
ThreadLocal
根据Android开发艺术探索的说明:threadLocal是一个线程内部的数据存储类,通过它可以在指定线程中存储数据,数据存储后只能在指定线程获取。
demo验证:
public class ThreadLocalDemoActivity extends AppCompatActivity {
private final String TAG = getClass().getSimpleName();
ThreadLocal<Boolean> test = new ThreadLocal<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_thread_local_demo );
Log.d( TAG,"主线程: test "+test.get() );
test.set( false );
Log.d( TAG,"主线程: test "+test.get() );
new Thread( new Runnable() {
@Override
public void run() {
test.set( true );
Log.d( TAG,"线程1: test "+test.get() );
}
} ).start();
new Thread( new Runnable() {
@Override
public void run() {
Log.d( TAG,"线程2: test "+test.get() );
}
} ).start();
}
}
验证结果:
在主线程中第一次获取到的值是null,然后设置为false,主线程第二次获取为false。
在子线程1中开始就设置值为true,获取到的值为true
在子线程2中直接进行获取值为null。
验证了ThreadLocal只能在指定线程获取数据。
ThreadLocal原理
Thread内部维护着一个ThreadLocalMap:threadLocals对象,threadLocals在Thread中没有初始化。它的初始化来自ThreadLocal
我们来看看ThreadLocal的set方法
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
getMap方法返回的就是当前线程维护的那个threadLocals对象,如果getMap返回对象不为空就以当前的ThreadLocal对象为key,将value放入threadLocals。如果为空那么就重新创建一个ThreadLocalMap并将值存放进去。我们这里不对ThreadLocalMap的具体存储过程进行分析。
ThreadLocal的get()方法
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = ma