android主线程与Handler
2019-10-30 本文已影响0人
丸子不爱吃丸子
回忆一个简单的Handler使用
class TestActivity : AppCompatActivity() {
private var mUIHandler = Handler{
when(it.what) {
1 -> {
Log.d("ggp", "hello handler")
}
2 -> {
Log.d("ggp", "hello handler")
}
}
false
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test)
}
}
大家都知道,子线程需要更新UI的时候是需要发送消息给主线程handler,然后处理ui,那么好奇一下这里的handler是怎么与activity 主线程(UI线程)绑定的?
首先好奇一下Activity主线程是啥?
回到ActivityThread中看一下mian是怎么实现的
public static void main(String[] args) {
............
//创建looper
Looper.prepareMainLooper();
...........
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
//拿到handler
sMainThreadHandler = thread.getHandler();
}
...............
//进入looper无线循环
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
准备主线程 looper prepareMainLooper
public static void prepareMainLooper() {
//准备looper
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
//get到looper
sMainLooper = myLooper();
}
}
继续
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//与上边遥相呼应 这里set,将当前looper set给sThreadLocal
sThreadLocal.set(new Looper(quitAllowed));
}
looper构造函数
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
这里new 了一个MessageQueue,设置thread为当前Thread,也就activityThread自己。
继续回到Activity 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());
}
}
//获取到当前looper
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
分析一下,这里获取到当前thead的looper,由于我们activity是跑在主进程,当然获取到的就是主线程的looper,继续想一下我们向handler发送消息,就是发送给了主线程Looper。
当前activity中的UIHandler其实拿到了主线程的Looper然后就可以处理主线程任务啦。
activity可以有多个Handler但是拿到的都是主线程的looper。因为在new Handler的时候就自动绑定了主线程looper。
顺道看一下HandlerThread使用
private var mHandlerThread: HandlerThread? = HandlerThread("ggpthread")
fun test() {
mGgpHandler = Handler(mHandlerThread!!.looper) {
when(it.what){
1 -> {
Log.d("ggp", "hello HandlerThread")
}
}
false
}
}
使用相当简单,这里需要对比一下HandlerThread,在使用第一要务就是getlooper(),我这里使用kotlin写的demo,java也是一样的。看一下getLooper怎么实现的
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
这里wait,等待mLooper初始化,看一下mLooper初始化:
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
当前Thread run中初始化,并且开始looper循环。
总结一下,初始化HandlerThread之后我们就会调用线程start