Android Activity启动到组件渲染(一)

这篇文章是从ActivityThread被调用开始分析的,这之前的流程暂时不做具体分析,以后有时间再加。

当用户点击桌面的图标或者代码直接拉起应用时,都需要调用startActivity,此时ActivityManagerServices就会通知zygote创建一个ApplicationProcess的进程,该进程是ActivityThread类

ActivityThread.java

public static void main(String[] args) {
	 	...
        Looper.prepareMainLooper();
        
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
	    ...
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

main方法的ActivityThread的入口,它在该方法创建了Looper,并调用loop(),使得Activity能源源不断地接收其他进程传递过来的消息,并处理这些消息,这部分属于Android消息机制的范畴,这里就不做分析了。我们可以看到在main方法中调用了attach方法,我们来看看里面主要做了什么。
ActivityThread.java

final ApplicationThread mAppThread = new ApplicationThread();

private void attach(boolean system) {
   	...
     RuntimeInit.setApplicationObject(mAppThread.asBinder());
     final IActivityManager mgr = ActivityManager.getService();
     try {
          mgr.attachApplication(mAppThread);
     } catch (RemoteException ex) {
         throw ex.rethrowFromSystemServer();
      }
       ...
    }

可以看到ActivityThread.java里面有一个全局变量mAppThread,ActivityManager.getService()返回的其实就是ActivityManagerService的引用,调用它的attachApplication方法。
ActivityManagerService.java

@Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }

接着是attachApplicationLocked

private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {
    ...
    // See if the top visible activity is waiting to run in this process...
    if (normalMode) {
        try {
            if (mStackSupervisor.attachApplicationLocked(app)) {
                didSomething = true;
            }
        } catch (Exception e) {
            Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
            badApp = true;
        }
    }
   ...
}

这段代码很长,前面有很多需要判断处理的情况,我们一一略过,只摘取其关键的部分,当前的Activity属于正常状态下,会调用mStackSupervisor.attachApplicationLocked(方法),它调用的是ActivityStackSupervisor.java类中的方法,继续分析。

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
        ...
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (!isFocusedStack(stack)) {
                    continue;
                }
                ActivityRecord hr = stack.topRunningActivityLocked();
                if (hr != null) {
                    if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                            && processName.equals(hr.processName)) {
                        try {
                        // 遍历栈并挑选合适的栈
                            if (realStartActivityLocked(hr, app, true, true)) {
                                didSomething = true;
                            }
                        } catch (RemoteException e) {
                            Slog.w(TAG, "Exception in new application when starting activity "
                                  + hr.intent.getComponent().flattenToShortString(), e);
                            throw e;
                        }
                    }
                }
            }
        }
        ...
    }

这里就是遍历所有的栈,找到能启动这个Activity的栈,执行realStartActivityLocked,任重而道远啊,继续。。。。

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {            
    ...
    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
            System.identityHashCode(r), r.info,
            // TODO: Have this take the merged configuration instead of separate global and
            // override configs.
            mergedConfiguration.getGlobalConfiguration(),
            mergedConfiguration.getOverrideConfiguration(), r.compat,
            r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
            r.persistentState, results, newIntents, !andResume,
            mService.isNextTransitionForward(), profilerInfo);
       ...
}

这段代码也很长,但是我们可以看到关键的一点,调用了app.thread.scheduleLaunchActivity(…)这个方法,这里的这个thread其实就是ActivityThread调用attachApplication是传递过来的thread,到这一步我们又回到了ActivityThread,来看看ApplicationThread的scheduleLaunchActivity 的里面做了什么。

private class ApplicationThread extends IApplicationThread.Stub {
        ...
    // we use token to identify this activity without having to send the
    // activity itself back to the activity manager. (matters more with ipc)
    @Override
    public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
            CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
            int procState, Bundle state, PersistableBundle persistentState,
            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
            boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
        updateProcessState(procState, false);
       ...
        sendMessage(H.LAUNCH_ACTIVITY, r);
    }
    ...
}

这个类也很长,我们先不去管其他方法,其实这个方法只是发出一条message消息而已,接着分析这个消息的处理。

 private class H extends Handler {
    	...
        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                ....
            }
            Object obj = msg.obj;
            if (obj instanceof SomeArgs) {
                ((SomeArgs) obj).recycle();
            }
            if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
        }
        ...
    }

这个H类是ActivityThread的一个全局变量,这里暂不做解析,我们可以看到调用了handleLaunchActivity方法,继续分析。

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    ...
    // Initialize before creating the activity
    WindowManagerGlobal.initialize();
    
    Activity a = performLaunchActivity(r, customIntent);
    if (a != null) {
        ...
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
        ...
    } else {
        // If there was an error, for any reason, tell the activity manager to stop us.
        try {
            ActivityManager.getService()
                .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                        Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }
}

这里调用了两个比较重要的方法,performLaunchActivity和handleResumeActivity两个方法了,我们先来分析performLaunchActivity

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
	...
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = appContext.getClassLoader();
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        ....
    } catch (Exception e) {
       ...
    }

    try {
        ...
        if (activity != null) {
            ...
            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);
            ...
            activity.mCalled = false;
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            ...
        }
       ...
    } catch (SuperNotCalledException e) {
        throw e;
    } catch (Exception e) {
       ...
    }
    return activity;
}

同样的,我们省略一些不重要的代码,在performLaunchActivity里看到显示创建了一个Activity对象,然后调用Activity的attach,然后执行callActivityOnCreate方法,这个方法从字面意思上就是让Activity调用onCreate方法,我们继续看看它的实现,果不其然,调用了performCreate方法,Activity的生命周期方法都是由Instrumentation对象来调用的。

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

在performLaunchActivity中最关键的还是attach方法,我们来分析一下它。

final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback) {
        attachBaseContext(context);
        //mWindow是一个非常重要的变量
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        //各种参数赋值给Activity
        ...
        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.mWindow成员变量赋值,然后给mWindow变量设置WindowManager,然后给Activity.mWindowManager赋值。

mWindow是一个Window类型的变量,但实际上它是一个PhoneWindow对象,与Activity的内容显示相关。

就之前分析可知attach执行完了就会执行oncreate方法,按一般的情况,Activity中的onCreate()方法调用了setContentView()方法,而setContentView()方法并不是由Activity实现的,我们看一下setContentView()方法。

public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
}

getWindow返回的就是attach方法中生成的mWindow变量,那么setContentView方法调用的就是PhoneWindow对象的的方法。
至此我们可以看到Activity真正渲染的过程不是在Activity中实现的,而是在PhoneWindow中实现。

PhoneWindow是抽象类Window的实现类,Window类用来描述Acitivity视图最顶端的窗口显示和行为操作,PhoneWindow里包含一个DecorView的对象,DecorView类继承FrameLayout,我们看一下PhoneWindow的setContentView()方法。

@Override
public void setContentView(int layoutResID) {
    if (mContentParent == null) {
        installDecor();//初始化DectorView
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        mContentParent.removeAllViews();
    }
    if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        ...
    } else {
        mLayoutInflater.inflate(layoutResID, mContentParent); //layoutResID被inflate出来
    }
    ...
}

setContentView方法初始化DectorView,并且通过LayoutInflater加载layoutResID资源的组件放在mContentParent中,这个变量是一个ViewGroup对象,是在installDecor()方法中被定义的。

private void installDecor() {
        mForceDecorInstall = false;
        if (mDecor == null) {
            mDecor = generateDecor(-1);
            ...
        } ...
        if (mContentParent == null) {
            mContentParent = generateLayout(mDecor);
            ...
        }...
    }

在generateDecor(-1)中创建了一个新的DecorView,generateLayout(mDecor)是根据window的各种属性inflate出不同的layout挂到DecorView下面,而mContentParent是这个layout中的一个子ViewGroup。

protected ViewGroup generateLayout(DecorView decor) {
        ...//根据Activity设置的属性值配置Window的LocalFeatrues、WindowManager.LayoutParam等等
        // Inflate the window decor.
        int layoutResource;
        int features = getLocalFeatures();
        // System.out.println("Features: 0x" + Integer.toHexString(features));
        if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
            layoutResource = R.layout.screen_swipe_dismiss;
            ...
        } else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
            if (mIsFloating) {
                ...
                layoutResource = res.resourceId;
            } else {
                layoutResource = R.layout.screen_title_icons;
            }
            ...
        } else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0
                && (features & (1 << FEATURE_ACTION_BAR)) == 0) {
            layoutResource = R.layout.screen_progress;
        } else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
           ...
                layoutResource = R.layout.screen_custom_title;
            ...
        } else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
            ...
                layoutResource = R.layout.screen_title;
          ...
        } else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
            layoutResource = R.layout.screen_simple_overlay_action_mode;
        } else {
            // Embedded, so no decoration is needed.
            layoutResource = R.layout.screen_simple;
        }
        mDecor.startChanging();
        mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
       ...
        return contentParent;
    }

如果我们没有对window的属性进行设置就会使用默认的com.android.internal.R.layout.screen_simple这个layout。这个layout最外层是一个LinearLayout。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical">
    <ViewStub android:id="@+id/action_mode_bar_stub"
              android:inflatedId="@+id/action_mode_bar"
              android:layout="@layout/action_mode_bar"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:theme="?attr/actionBarTheme" />
    <FrameLayout
         android:id="@android:id/content"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:foregroundInsidePadding="false"
         android:foregroundGravity="fill_horizontal|top"
         android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>

里面包含了一个action_bar和一个content显示内容,至此,我们可以画一张图来表示一下现有布局的层级关系。
Activity布局管理

installDecor()方法被调用后就会生成mDecor以及mContentParent,最后在setContentView方法中会通过InflaterLayout类将传入的layoutResID加载到mContentParent组件中,这就是Activity大致的布局管理了。

总结

至此ActivityThread执行performLaunchActivity()方法基本分析完成,可以看到performLaunchActivity()方法加载了一个Activity类,并执行了它的onCreate方法,初始化了PhoneWindow、DecorWindow类的对象用于Activity的布局管理。

Android Activity启动到组件渲染(二)

发布了7 篇原创文章 · 获赞 1 · 访问量 434

猜你喜欢

转载自blog.csdn.net/hust_edu_csdn_123/article/details/84659702