Android的Activity啟動與子執行緒更新UI

weixin_34007291發表於2016-02-14

最近會將以前閱讀過的一些原始碼做些沉澱與總結
我們知道現在大多數的GUI框架都是採用單執行緒模型來處理訊息佇列和UI更新的,Android自然也是如此。

啟動

在APK首次啟動的時候,Zygote程式會fork個子程式,並在子程式中呼叫ActivityThread的main函式,主執行緒的訊息佇列和ActivityThread例項的初始化都是在此完成的。

與AMS的通訊

ActivtyManagerService控制著Activity的啟動與生命週期,並通過ApplicationThread與ActivityThread進行IPC通訊。

onCreate

AMS通過ApplicationThread的scheduleLaunchActivity啟動一個新的Activity,並通過Handler呼叫ActivityThread的handleLaunchActivity方法。

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent)  {    
    ......
    Activity a = performLaunchActivity(r, customIntent);
    if  (a != null)  {   
        r.createdConfig = new Configuration(mConfiguration);    
        Bundle oldState = r.state;    
        handleResumeActivity(r.token, false, r.isForward,            
        !r.activity.mFinished && !r.startsNotResumed);
    ......
}

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent)  {
    ......
    if  (r.isPersistable())  {    
        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
    } 
    else  {    
        mInstrumentation.callActivityOnCreate(activity, r.state);
    }
    ......
}


Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle, PersistableBundle persistentState)  {    
    prePerformCreate(activity);    
    activity.performCreate(icicle, persistentState);    
    postPerformCreate(activity);
}


Activity.java
final void performCreate(Bundle icicle, PersistableBundle persistentState)  {   
   onCreate(icicle, persistentState);    
   mActivityTransitionState.readState(icicle);    
   performCreateCommon();
}

onResume

ActivtyThread通過performLaunchActivity的呼叫做些Activity的初始化,包括建立例項和最終呼叫Activity的onCreate方法。之後通過呼叫handleResumeActivity方法

final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume)  {
    ......
    // TODO Push resumeArgs into the activity for consideration
    ActivityClientRecord r =  performResumeActivity(token, clearHide);
    ......
    if (r.window == null && !a.mFinished && willBeVisible)  {   
        if (a.mVisibleFromClient)  {   
            a.mWindowAdded = true;    
            wm.addView(decor, l);
        }
    }
    .....

public final ActivityClientRecord performResumeActivity(IBinder token, boolean clearHide)  {
    ......
    r.activity.performResume();
    ......
}

ActivtyThread通過handleResumeActivity呼叫Activity的onResume方法之後,並在當前Activity的Window為null等情況下,呼叫WindowMangerGlobal的addView方法將Activity的decorView新增在Window中。

WindowMangerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow)  {
    ......
    root = new ViewRootImpl(view.getContext(), display);
    view.setLayoutParams(wparams);
    try  {    
        root.setView(view, wparams, panelParentView);
    } catch (RuntimeException e) {
    ......
}

重點來了,在Activity的onCreate和onResume呼叫之後,ActivityThread才建立了ViewRootImpl,並呼叫setView方法

ViewRootImpl.java  
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView)  {
    ......
    requestLayout();
    ......
    view.assignParent(this);
  ......
}

@Override
public void requestLayout()  {    
    if  (!mHandlingLayoutInLayoutRequest)  {        
        checkThread();       
        mLayoutRequested = true;        
        scheduleTraversals();    
    }
}
void invalidate()  {
    mDirty.set(0, 0, mWidth, mHeight);
    if  (!mWillDrawSoon)  {    
        scheduleTraversals();
    }
}

在此才會檢查當前執行緒是否為主執行緒,並設定了view的parent,之後一些系統view元件或自定義view會通過呼叫requestlayout或者invalidate實現view的重新渲染(scheduleTraversals通過Handelr實現)。

結論

通過上訴Activity的啟動過程可知,我們在Activity的onCreate和onResume中,通過子執行緒的確可以實現更新某些系統view元件。

@Override
protected void onResume()  {    
    super.onResume();    
    new NoUIThread().start();
}
class NoUIThread extends Thread  {
    @Override
    public void run()  {
        mNoUITextView.setText("Penner");
    }
}

相關文章