Potato icon indicating copy to clipboard operation
Potato copied to clipboard

Activity: Lifecycle and ActivityThread

Open yunshuipiao opened this issue 5 years ago • 0 comments

Activity: Lifecycle and ActivityThread

[TOC]

之前说了 App 的大概启动流程,在 Launcher 进程也是通过 startActivity 方法启动 Activity。经过一系列进程创建,Application 初始化之后,MainActivity.onCreate() 方法将会执行,这篇文章就从开始入手分析。

onCreate 过程

ActivityThread.handleLaunchActivity

启动 Activity 的整个过程最终都会调用该方法,部分代码和注释如下:

// 当Server 请求启动或者重启时,实现 Activity 的启动,
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, Intent customIntent) {
  
  // 创建 Activity
  final Activity a = performLaunchActivity(r, customIntent);
  return a
}

// 启动 Activity 和核心方法
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
  		// AndroidManifest 中关于 Activity 的相关信息
      ActivityInfo aInfo = r.activityInfo;
  			// loadedApk 对象,表示 apk 在内存的所有信息表示
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }
				// application 中确定唯一的四大组件的类,由 package 名和 class 名两个因素封装而成。
        ComponentName component = r.intent.getComponent();
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }

        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }
				
  
  			//  上下文对象
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
          	// 类加载器
            java.lang.ClassLoader cl = appContext.getClassLoader();
          	// 创建 Activity
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
        }

        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

           

            if (activity != null) {
                // 将一系列字段传入 Activity
                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);

                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                  	// 调用 Activity.onCreate()
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }

        return activity;
}

上面代码有删减,到此为止,MainActivity.onCreate() 方法已经执行,看一下其中的 activity.attach() 方法,

主要是 PhoneWindow 和对应 WindowManger 对象的设置

final void attach(...) {
  	// 创建 PhoneWindow 对象
		mWindow = new PhoneWindow(this, window, activityConfigCallback);
    //  设置 windowManager 
  	mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
    mWindowManager = mWindow.getWindowManager();
}	

回到 Activity.onCreate() 方法:

// Instrumentation
public void callActivityOnCreate(Activity activity, Bundle icicle) {
    prePerformCreate(activity);
    activity.performCreate(icicle);
    postPerformCreate(activity);
}
		// Activity
    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
       
      	// 执行 onCreate
        if (persistentState != null) {
            onCreate(icicle, persistentState);
        } else {
            onCreate(icicle);
        }
        // fragment 的生命周期
        mFragments.dispatchActivityCreated();
      	// 转换动画
        mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
    }

    @MainThread
    @CallSuper
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        // 恢复保存的数据,如果有的话
        if (savedInstanceState != null) {
            mAutoFillResetNeeded = savedInstanceState.getBoolean(AUTOFILL_RESET_NEEDED, false);
            mLastAutofillId = savedInstanceState.getInt(LAST_AUTOFILL_ID,
                    View.LAST_APP_AUTOFILL_ID);

            if (mAutoFillResetNeeded) {
                getAutofillManager().onCreate(savedInstanceState);
            }

            Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
            mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
                    ? mLastNonConfigurationInstances.fragments : null);
        }
      	// fragment 生命周期回调
        mFragments.dispatchCreate();
      	// ActivityLifecycleCallbacks 回调
        getApplication().dispatchActivityCreated(this, savedInstanceState);
        if (mVoiceInteractor != null) {
            mVoiceInteractor.attachActivity(this);
        }
        mRestoredFromBundle = savedInstanceState != null;
        mCalled = true;
    }

在以上代码和部分注释的分析中,Activirty 完成了创建,同时创建了 PhoneWindow。紧接着就需要手动调用setContentView() 方法设置布局。

setContentView

// 设置 Activity 的显示内容,位于最上面
public void setContentView(@LayoutRes int layoutResID) {
    getWindow().setContentView(layoutResID);
  	// 设置 actionbar
    initWindowDecorActionBar();
}
		// PhoneWindow.java
		@Override
    public void setContentView(int layoutResID) {
        // window 要放置的view,Decor 或者其子view
        if (mContentParent == null) {
          	// 初始化 WindowDecor,是 window 最上层的 view,并包含 Decor。
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
          	// 从 xml 布局中创建 view, 添加到 parent
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
          	// 内容改变的回调
            cb.onContentChanged();
        }
        mContentParentExplicitlySet = true;
    }

在 mLayoutInflater.inflate(layoutResID, mContentParent); 中有两个特别重要的地方,代码如下:

// 忽略 Xml 解析内容的部分,看下关键代码
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
    synchronized (mConstructorArgs) {
        try {
            // merge 节点,tag
            if (TAG_MERGE.equals(name)) {
                if (root == null || !attachToRoot) {
                    throw new InflateException("<merge /> can be used only with a valid "
                            + "ViewGroup root and attachToRoot=true");
                }
               	// 递归方法,用于向下传递xml层次结构并实例化视图、实例化其子视图,然后调用onfinishinflation()。
                rInflate(parser, root, inflaterContext, attrs, false);
            } else {
                // Inflate all children under temp against its context.
              	// 与上面一样,除了 parent, 见下
                rInflateChildren(parser, temp, attrs, true); 
            }
        return result;
    }
}
final void rInflateChildren(XmlPullParser parser, View parent, AttributeSet attrs,
        boolean finishInflate) throws XmlPullParserException, IOException {
    rInflate(parser, parent, parent.getContext(), attrs, finishInflate);
}

void rInflate(XmlPullParser parser, View parent, Context context,
        AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException {
		// 节点深度
    final int depth = parser.getDepth();
    int type;
    boolean pendingRequestFocus = false;
		// 判断何时结束
    while (((type = parser.next()) != XmlPullParser.END_TAG ||
            parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {

        if (type != XmlPullParser.START_TAG) {
            continue;
        }
				// 获取 view 名字 
        final String name = parser.getName();

        if (TAG_REQUEST_FOCUS.equals(name)) {
            pendingRequestFocus = true;
            consumeChildElements(parser);
        } else if (TAG_TAG.equals(name)) {
            parseViewTag(parser, parent, attrs);
          // include tag
        } else if (TAG_INCLUDE.equals(name)) {
            if (parser.getDepth() == 0) {
                throw new InflateException("<include /> cannot be the root element");
            }
            parseInclude(parser, context, parent, attrs);
          // merge tag
        } else if (TAG_MERGE.equals(name)) {
            throw new InflateException("<merge /> must be the root element");
        } else {
          	// 普通的 view 实力化
            final View view = createViewFromTag(parent, name, context, attrs);
            final ViewGroup viewGroup = (ViewGroup) parent;
            final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
          	// 循环,知道结束
            rInflateChildren(parser, view, attrs, true);
            viewGroup.addView(view, params);
        }
    }

    if (pendingRequestFocus) {
        parent.restoreDefaultFocus();
    }
		
  	// 结束
    if (finishInflate) {
        parent.onFinishInflate();
    }
}

在这个部分,两个函数循环调用,直到 xml 中所有的 View 解析完毕,调用 parent.onFinishInflate() 方法,完成整个过程。

start 过程

//ActivityThread
@Override
public void handleStartActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions) {
  			// 没有经过 stop ,不能start
        if (!r.stopped) {
            throw new IllegalStateException("Can't start activity that is not stopped.");
        }
  			        // Start
  			// 处理start 过程
        activity.performStart("handleStartActivity");
  			// 设置状态
        r.setState(ON_START);
}

// Activity
final void performStart(String reason) { 
   // 调用 Activity.start 方法
   mInstrumentation.callActivityOnStart(this);
   mFragments.dispatchStart();
   mFragments.reportLoaderStart();
}

resume 过程

@Override
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
        String reason) {
 
    if (r.window == null && !a.mFinished && willBeVisible) {
        r.window = r.activity.getWindow();
        View decor = r.window.getDecorView();
      	// 先将 decor 置为不可见
        decor.setVisibility(View.INVISIBLE);
        ViewManager wm = a.getWindowManager();
        WindowManager.LayoutParams l = r.window.getAttributes();
        a.mDecor = decor;
        l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
        l.softInputMode |= forwardBit;
        if (r.mPreserveWindow) {
            
        }
        if (a.mVisibleFromClient) {
            if (!a.mWindowAdded) {
                a.mWindowAdded = true;
              	// 将 Decor 加入到 window 中
                wm.addView(decor, l);
            } else {
                // 添加过就通知改变
                a.onWindowAttributesChanged(l);
            }
        }

        r.activity.mVisibleFromServer = true;
        mNumVisibleActivities++;
        if (r.activity.mVisibleFromClient) {
          	// 设置可见
            r.activity.makeVisible();
        }
    }
}

这个函数中, 首先是调用 performResumeActivity,使 Activity 进入 resume 状态。接着将 DecorView 添加到 Window 中并显示出来。

wm.addView()

下面来看一下这个过程。

	// 从 activity 中添加或者移除 view
public interface ViewManager
{
    public void addView(View view, ViewGroup.LayoutParams params);
    public void updateViewLayout(View view, ViewGroup.LayoutParams params);
    public void removeView(View view);
}

真正的实现在 WindowMangerImpl 中。

// WindowMangerImpl.java
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    applyDefaultToken(params);
    mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}

// WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
  ...
            root = new ViewRootImpl(view.getContext(), display);

            view.setLayoutParams(wparams);

            mViews.add(view);
            mRoots.add(root);
            mParams.add(wparams);
  					try {
                root.setView(view, wparams, panelParentView);
            }
  ...
}

在 WindowMangerGlobal 中保存了一系列 ViewRootImpl 实例。每增加一个布局,就会创建一个 ViewRootimpl 对象。

// 
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    synchronized (this) {
      if(mView != null) {
        ...
        requestLayout();
      }
}
  
 @Override
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }
  		
 		// 线程检查:只有在 onResume 之后,Activity 才会在检查是否在 UI 线程更新 UI。
     void checkThread() {
        if (mThread != Thread.currentThread()) {
            throw new CalledFromWrongThreadException(
                    "Only the original thread that created a view hierarchy can touch its views.");
        }
    }

在上面的过程中,最终会执行到 ViewRootImpl.performTraversals() 方法,后面就是 View 的绘制流程。

总结

这篇文章主要接着 App 的启动,分析 Application 创建之后,ActivityThread 和 Instumentation 控制执行 Activity 生命周期方法的流程,从 create, start 到 resume,中间与 fragment 和相关生命周期等。

yunshuipiao avatar May 18 '19 18:05 yunshuipiao