在Android中,常用的主线程同步方式有以下几种:

  1. Activity.runOnUiThread(Runnable)
  2. View.post(Runnable)、View.postDelay(Runnable, long)
  3. AsyncTask
  4. 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(this, values)).sendToTarget();        }    }    private Result postResult(Result result) {        @SuppressWarnings("unchecked")        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,                new AsyncTaskResult(this, result));        message.sendToTarget();        return result;    }

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) {    }

 

更多相关文章

  1. 【知识点】android代码中设置margin
  2. Android(安卓)获取当前日期 时间很方便 直接调用Calendar类即可
  3. Android调用相机和相册详解
  4. 如何制作Jar包并在android中调用jar包
  5. Android(安卓)最新获取手机内置存储大小,SD卡存储空间大小方法
  6. WebKit – WebKit For Android
  7. Android遍历文件Listfile返回值为null问题解决方法适用Android8.
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. android极简原创系列:三层结构和.net
  2. android实现从相册和相机中取照片并剪辑
  3. Android 中 ThreadLocal使用示例
  4. Android system/bin 命令
  5. Android 的R类
  6. Android 如何处理Search下的suggestion q
  7. Android Studio开发过程中各种问题
  8. Android Studio编译运行project报错:··
  9. Android GPS获得经纬度并得到该坐标精确
  10. Android全屏设置及取消全屏设置