在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中Bitmap的放大和缩小的方法
  2. Android遍历文件Listfile返回值为null问题解决方法适用Android8.
  3. Android 最新获取手机内置存储大小,SD卡存储空间大小方法
  4. Android 启动浏览器的方法
  5. Android根据电量变化为不同图片的方法【电池电量提示】
  6. Android之日期时间选择器使用方法
  7. Android 图片旋转(使用Matrix.setRotate方法)
  8. Android Http请求失败解决方法
  9. Glide的with()方法和生命周期的源码分析

随机推荐

  1. [翻译]微服务设计模式 - 4. 服务发现 -
  2. [翻译]微服务设计模式 - 3. 按业务功能拆
  3. 对linux配置文件的处理----grep&sed
  4. 腾讯:手Q研发体系与工具实践
  5. 掌握这几个技巧,以后用MySQL查询总比别人
  6. 从作坊到工厂 — 传统企业 DevOps 改造历
  7. 0104 函数练习
  8. MongoDB系列12:MongoDB电子商务产品目录模
  9. Java高并发编程基础三大利器之CountDownL
  10. spark源码阅读基本思路