Android中工作线程与主线程同步方式
在Android中,常用的主线程同步方式有以下几种:
- Activity.runOnUiThread(Runnable)
- View.post(Runnable)、View.postDelay(Runnable, long)
- AsyncTask
- Handler
这几种方式其原理都是一样的,都是基于Handler。
1、Activity.runOnUiThread(Runnable)
runOnUiThread是Activity中的一个final方法,不可以被重写,接受一个Runnable对象,其内部实现首先是判断当前线程是不是UI线程,如果是UI线程则直接调用Runnable的run()方法,如果不是,则通过Handler将Runnablepost到主线程,此Handler为主线程的Handler。
public final void runOnUiThread(Runnable action) { if (Thread.currentThread() != mUiThread) { mHandler.post(action); } else { action.run(); }}
这里的mUiThread在Activity的attach()方法中得到初始化。
final void attach(...) { ... mUiThread = Thread.currentThread(); ...}
这里的mUiThread 为什么会是主线程呢?
我们知道,当Zygote孵化出一个进程之后,便会执行ActivityThread中的main()方法,main()方法中初始化了mainLooper,随后new了一个ActivityThread对象,初始化了一个名为mH的Handler,然后进行Looper.loop()操作。
public static void main(String[] args) { ... Looper.prepareMainLooper(); ... ActivityThread thread = new ActivityThread(); thread.attach(false, startSeq); ... Looper.loop();}
在mH中是这样实现的,然后调用handleLaunchActivity,最后执行Activity的attach方法,便初始化了mUiThread。
class H extends Handler { ... public void handleMessage(Message msg) { .... case LAUNCH_ACTIVITY: handleLaunchActivity(r, null, "LAUNCH_ACTIVITY"); break; .... }}private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) { ... Activity a = performLaunchActivity(r, customIntent); ...}private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ... Activity activity = null; activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent); activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor, window, r.configCallback); ...}
2、View.post(Runnable)、View.postDelay(Runnable, long)
public boolean post(Runnable action) { final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { return attachInfo.mHandler.post(action); } getRunQueue().post(action); return true;}public boolean postDelayed(Runnable action, long delayMillis) { final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { return attachInfo.mHandler.postDelayed(action, delayMillis); } getRunQueue().postDelayed(action, delayMillis); return true;}
两个方法都会先判断attachInfo是否为空,如果不为空则执行Handler.post(),那么attachInfo的赋值情况如何呢?
void dispatchAttachedToWindow(AttachInfo info, int visibility) { mAttachInfo = info;}void dispatchDetachedFromWindow() { mAttachInfo = null;}
dispatchAttachedToWindow和dispatchDetachedFromWindow何时被调用这里不做展开,当attachInfo为空时,也就是执行了dispatchDetachedFromWindow之后,post的Runnable便会被加入到mRunQueue中,这里可以暂且将其理解为一个Runnable数组,当下次调用dispatchAttachedToWindow后,便会从mRunQueue中拿出Runnable依次执行handler.postDelayed。
void dispatchAttachedToWindow(AttachInfo info, int visibility) { ... if (mRunQueue != null) { mRunQueue.executeActions(info.mHandler); mRunQueue = null; } ...}public void executeActions(Handler handler) { synchronized (this) { final HandlerAction[] actions = mActions; for (int i = 0, count = mCount; i < count; i++) { final HandlerAction handlerAction = actions[i]; handler.postDelayed(handlerAction.action, handlerAction.delay); } mActions = null; mCount = 0; }}
3、AsyncTask
在AsyncTask中有一个名为mHandler的Handler,可以通过getHandler拿到,通常我们使用AsyncTask都是调用AsyncTask的无参构造方法,而无参构造方法会初始化主线程的Handler。在AsyncTask中,onPreExecute、onCancelled、onPostExecute、onProgressUpdate都会在主线程被调用,除onPreExecute是在一开始就被调用外,其余方法皆是通过Handler让其在主线程执行。
protected final void publishProgress(Progress... values) { if (!isCancelled()) { getHandler().obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult
mHandler就是AsyncTask内部的InternalHandler
private static class InternalHandler extends Handler { public InternalHandler(Looper looper) { super(looper); } @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"}) @Override public void handleMessage(Message msg) { AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj; switch (msg.what) { case MESSAGE_POST_RESULT: // There is only one result result.mTask.finish(result.mData[0]); break; case MESSAGE_POST_PROGRESS: result.mTask.onProgressUpdate(result.mData); break; } } } private void finish(Result result) { if (isCancelled()) { onCancelled(result); } else { onPostExecute(result); } mStatus = Status.FINISHED; } protected void onProgressUpdate(Progress... values) { }
更多相关文章
- android中Bitmap的放大和缩小的方法
- Android遍历文件Listfile返回值为null问题解决方法适用Android8.
- Android 最新获取手机内置存储大小,SD卡存储空间大小方法
- Android 启动浏览器的方法
- Android根据电量变化为不同图片的方法【电池电量提示】
- Android之日期时间选择器使用方法
- Android 图片旋转(使用Matrix.setRotate方法)
- Android Http请求失败解决方法
- Glide的with()方法和生命周期的源码分析