Android的Activity启动与子线程更新UI

最近会将以前阅读过的一些源码做些沉淀与总结
我们知道现在大多数的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");
    }
}

你可能感兴趣的:(Android的Activity启动与子线程更新UI)