Android应用程序窗口(Activity,Window,View)原理解析
2. Android应用程序内部启动Activity过程(startActivity)的源代码分析。
Android应用程序窗口(Activity)的运行上下文环境(Context)的创建过程分析
ActivityThread
public final class ActivityThread {
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
newActivity mInstrumentation
ContextImpl appContext = new ContextImpl();
......
appContext.setOuterContext(activity);
new ContextImpl
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstance,
r.lastNonConfigurationChildInstances, config);
activity.attach();
ActivityThread
performLaunchActivity
mInstrumentation.callActivityOnCreate(activity, r.state);
activity.performCreate(icicle, persistentState);
performCreate
Activity
final void performCreate(Bundle icicle) {
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
函数主要就是调用当前正在启动的Activity组件的成员函数onCreate,用来通知它已经成功地创建和启动完成了。
Activity
protected void onCreate(@Nullable Bundle savedInstanceState) {
callActivityOnCreate
public class Instrumentation {
......
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return (Activity)cl.loadClass(className).newInstance();
}
......
}
newActivity
cl.loadClass className.newInstance
ContextImpl
class ContextImpl extends Context {
ContextImpl Activity)的运行上下文环境(Context)的创建过程分析,当一个ContextImpl对象是用来描述一个Activity组件的运行上下文环境时,
ActivityThread
activity.attach(appContext, this, getInstrumentation(), r.token,
Activity
public class Activity extends ContextThemeWrapper
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
attach
ContextThemeWrapper
attachBaseContext(context);
attachBaseContext
Activity
mWindow = PolicyManager.makeNewWindow(this);
makeNewWindow
PolicyManager
public static Window makeNewWindow(Context context) {
Policy
public Window makeNewWindow(Context context) {
return new PhoneWindow(context);
}
PhoneWindow
Activity
mWindow.setCallback(this);
Window
public final Callback getCallback() {
return mCallback;
}
PhoneWindow
final Callback cb = getCallback();
final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event)
: super.dispatchKeyEvent(event);
public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback,
Activity
public boolean dispatchKeyEvent(KeyEvent event) {
窗口管理者来管理 PhoneWindow对象从父类Window继承下来的成员函数setWindowManager来为它设置一个合适的窗口管理者
getWindowManager
setWindowManager getWindowManager
数就将它保存在Activity类的成员变量mWindowManager中 mWindowManager
Activity
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
setWindowManager
mWindowManager = mWindow.getWindowManager();
getWindowManager
Window
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
WindowManagerImpl
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
return new WindowManagerImpl(mDisplay, parentWindow);
}
mApplication = application;
ActivityThread
performLaunchActivity
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
LoadedApk
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
Instrumentation
return newApplication(cl.loadClass(className), context);
Application app = (Application)clazz.newInstance();
app.attach(context);
clazz.newInstance
cl.loadClass className
Application
public class Application extends ContextWrapper implements ComponentCallbacks2 {
final void attach(Context context) {
attachBaseContext(context);
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}
Activity
attach
attachBaseContext(context);
ContextThemeWrapper
@Override protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
}
attachBaseContext
ContextWrapper
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
Context mBase
ContextWrapper
mBase = ContextImpl
至此,一个Activity组件的创建过程,以及它的运行上下文环境的创建过程,就分析完成了。这个过程比较简单,我们是从中获得以下三点信息:
1. 一个Android应用窗口的运行上下文环境是使用一个ContextImpl对象来描述的,这个ContextImpl对象会分别保存在Activity类的父类ContextThemeWrapper和ContextWrapper的成员变量mBase中,即ContextThemeWrapper类和ContextWrapper类的成员变量mBase指向的是一个ContextImpl对象。
2. Activity组件在创建过程中,即在它的成员函数attach被调用的时候,会创建一个PhoneWindow对象,并且保存在成员变量mWindow中,用来描述一个具体的Android应用程序窗口。
3. Activity组件在创建的最后,即在它的子类所重写的成员函数onCreate中,会调用父类Activity的成员函数setContentView来创建一个Android应用程序窗口的视图。
ContextImpl应用窗口的运行上下文环境
attach -> PhoneWindow来描述一个具体的Android应用程序窗口
onCreate
Android应用程序窗口(Activity)的窗口对象(Window)的创建过程分析
PolicyManager
public final class PolicyManager {
private static final String POLICY_IMPL_CLASS_NAME =
"com.android.internal.policy.impl.Policy";
private static final IPolicy sPolicy;
static {
// Pull in the actual implementation of the policy at run-time
try {
Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
sPolicy = (IPolicy)policyClass.newInstance();
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
POLICY_IMPL_CLASS_NAME + " could not be loaded", ex);
} catch (InstantiationException ex) {
throw new RuntimeException(
POLICY_IMPL_CLASS_NAME + " could not be instantiated", ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException(
POLICY_IMPL_CLASS_NAME + " could not be instantiated", ex);
}
}
......
// The static methods to spawn new policy-specific objects
public static Window makeNewWindow(Context context) {
return sPolicy.makeNewWindow(context);
}
......
}
PolicyManager IPolicy
Class.forName sPolicy = policyClass.newInstance
PolicyManager是一个窗口管理策略类
Policy
public class Policy implements IPolicy {
......
public PhoneWindow makeNewWindow(Context context) {
return new PhoneWindow(context);
}
......
}
PhoneWindow
public class PhoneWindow extends Window implements MenuBuilder.Callback {
......
// This is the top-level view of the window, containing the window decor.
private DecorView mDecor;
// This is the view in which the window contents are placed. It is either
// mDecor itself, or a child of mDecor where the contents go.
private ViewGroup mContentParent;
......
private LayoutInflater mLayoutInflater;
......
public PhoneWindow(Context context) {
super(context);
mLayoutInflater = LayoutInflater.from(context);
}
......
}
mLayoutInflater = LayoutInflater.from(context);
变量mLayoutInflater来创建应用程序窗口的视图
public abstract class Window {
......
private final Context mContext;
......
public Window(Context context) {
mContext = context;
}
......
}
Activity
attach
setWindowManager来设置应用程序窗口的本地窗口管理器
这样,MainActivity就启动起来了,整个应用程序也启动起来了。
整个应用程序的启动过程要执行很多步骤,但是整体来看,主要分为以下五个阶段:
一. Step1 - Step 11:Launcher通过Binder进程间通信机制通知ActivityManagerService,它要启动一个Activity;
二. Step 12 - Step 16:ActivityManagerService通过Binder进程间通信机制通知Launcher进入Paused状态;
三. Step 17 - Step 24:Launcher通过Binder进程间通信机制通知ActivityManagerService,它已经准备就绪进入Paused状态,于是ActivityManagerService就创建一个新的进程,用来启动一个ActivityThread实例,即将要启动的Activity就是在这个ActivityThread实例中运行;
四. Step 25 - Step 27:ActivityThread通过Binder进程间通信机制将一个ApplicationThread类型的Binder对象传递给ActivityManagerService,以便以后ActivityManagerService能够通过这个Binder对象和它进行通信;
五. Step 28 - Step 35:ActivityManagerService通过Binder进程间通信机制通知ActivityThread,现在一切准备就绪,它可以真正执行Activity的启动操作了。
这里不少地方涉及到了Binder进程间通信机制,相关资料请参考Android进程间通信(IPC)机制Binder简要介绍和学习计划一文。
这样,应用程序的启动过程就介绍完了,它实质上是启动应用程序的默认Activity,在下一篇文章中,我们将介绍在应用程序内部启动另一个Activity的过程,即新的Activity与启动它的Activity将会在同一个进程(Process)和任务(Task)运行,敬请关注
Launcher通过Binder进程间通信机制通知ActivityManagerService,它要启动一个Activity;
Binder ActivityManagerService通过Binder进程间通信机制通知ActivityThread,现在一切准备就绪,它可以真正执行Activity的启动操作了。
Activity
ActivityManagerService通过Binder进程间通信机制通知ActivityThread,现在一切准备就绪,它可以真正执行Activity的启动操作了。
Binder Luncher Paused
ActivityStackSupervisor
final int startActivityLocked(IApplicationThread caller,
ActivityRecord
final class ProcessRecord
ProcessRecord callerApp = null;
if (caller != null) {
callerApp = mService.getRecordForAppLocked(caller);
IApplicationThread caller,
final ActivityManagerService mService;
final ArrayList<ProcessRecord> mLruProcesses = new ArrayList<ProcessRecord>();
传进来的参数caller得到调用者的进程信息,并保存在callerApp变量中,这里就是Launcher应用程序的进程信息了。
IBinder resultTo, 通过它可以获得Launcher这个Activity的相关信息
sourceRecord = isInAnyStackLocked(resultTo);
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, true, options, inTask);
由于在这个例子的AndroidManifest.xml文件中,MainActivity没有配置launchMode属值,因此,这里的r.launchMode为默认值0,表示以标准(Standard,或者称为ActivityInfo.LAUNCH_MULTIPLE)的方式来启动这个Activity。Activity的启动方式有四种,其余三种分别是ActivityInfo.LAUNCH_SINGLE_INSTANCE、ActivityInfo.LAUNCH_SINGLE_TASK和ActivityInfo.LAUNCH_SINGLE_TOP,具体可以参考官方网站
Activity.LAUNCH_SINGLE_INSTANCE、ActivityInfo
LAUNCH_SINGLE_TASK和ActivityInfo
LAUNCH_SINGLE_TOP,具体可以参考官方网站
LAUNCH_MULTIPLE)的方式来启动这个Activity。Activity的启动方式有四种,其余三种分别是ActivityInfo
此,在继续往下执行之前,首先要把当处于Resumed状态的Activity推入Paused状态,然后才可以启动新的Activity。
ActivityStack
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
prev.configChangeFlags);
prev.app.thread是一个ApplicationThread对象的远程接口,通过调用这个远程接口的schedulePauseActivity来通知Launcher进入Paused状态。
ApplicationThreadProxy.schedulePauseActivity
个函数通过Binder进程间通信机制进入到ApplicationThread.schedulePauseActivity函数中。
ApplicationThreadProxy.schedulePauseActivity
这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中,它是ActivityThread的内部类:
ApplicationThread.schedulePauseActivity
private final class ApplicationThread extends ApplicationThreadNative {
......
public final void schedulePauseActivity(IBinder token, boolean finished,
handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
msg.obj是一个ActivityRecord对象的引用,它代表的是Launcher这个Activity。
private final void handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges) {
ActivityClientRecord r = mActivities.get(token);
ActivityClientRecord =ActivityRecord
ActivityManagerNative.getDefault().activityPaused(token, state);
函数首先将Binder引用token转换成ActivityRecord的远程接口ActivityClientRecord,然后做了三个事情:
1. 如果userLeaving为true,则通过调用performUserLeavingActivity函数来调用Activity.onUserLeaveHint通知Activity,
用户要离开它了;
2. 调用performPauseActivity函数来调用Activity.onPause函数,我们知道,在Activity的生命周期中,
当它要让位于其它的Activity时,系统就会调用它的onPause函数;
3. 它通知ActivityManagerService,这个Activity已经进入Paused状态了,ActivityManagerService现在可以完成未竟的事情,
即启动MainActivity了
Android应用程序窗口(Activity)的视图对象(View)的创建过程分析
ActivityThread
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
activity.attach(appContext, this, getInstrumentation(), r.token,
ActivityThread
static final class ActivityClientRecord {
IBinder token;
Activity
inal void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
private IBinder mToken;
mToken = token;
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
mAppToken = appToken;
参数appToken用来描述当前正在处理的窗口是与哪一个Activity组件关联的,它是一个Binder代理对象,引用了在
WindowManagerImpl LocalWindowManager
getDefault
PhoneWindow
Android应用程序窗口(Activity)的视图对象(View)的创建过程分析
ActivityThread
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
activity.attach(appContext, this, getInstrumentation(), r.token,
ActivityThread
static final class ActivityClientRecord {
IBinder token;
Activity
inal void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
private IBinder mToken;
mToken = token;
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
mAppToken = appToken;
参数appToken用来描述当前正在处理的窗口是与哪一个Activity组件关联的,它是一个Binder代理对象,引用了在
WindowManagerImpl LocalWindowManager
getDefault
PhoneWindow
PhoneWindow
public class PhoneWindow extends Window implements MenuBuilder.Callback {
DecorView
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {
public class FrameLayout extends ViewGroup {
public abstract class ViewGroup extends View implements ViewParent, ViewManager {
public final class ActivityThread {
private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ViewRoot
Activity
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
其中,调用从父类Activity继承下来的成员函数setContentView就是用来创建应用程序窗口视图对象
PhoneWindow
public class PhoneWindow extends Window implements MenuBuilder.Callback
@Override
public void setContentView(int layoutResID) {
installDecor();
DecorView
private DecorView mDecor;
private void installDecor() {
if (mDecor == null) {
mDecor = generateDecor();
......
}
接下来就会调用ActivityThread类的另外一个成员函数handleResumeActivity来激活正在启动的Activity组件
handleResumeActivity
public final class ActivityThread {
......
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
handleResumeActivity
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
getWindow getDecorView getWindowManager
wm.addView(decor, l);
addView
这个ActivityClientRecord对象的成员变量activity描述的就是正在激活的Activity组件a。
ActivityClientRecord
Step 8. Activity.getWindow
Activity
public Window getWindow() {
return mWindow;
}
PhoneWindow
public class PhoneWindow extends Window imp
DecorView
private DecorView mDecor;
......
@Override
public final View getDecorView() {
if (mDecor == null) {
installDecor();
}
return mDecor;
}
getDecorView
WindowManager
Activity
private WindowManager mWindowManager;
......
public WindowManager getWindowManager() {
return mWindowManager;
}
LocalWindowManager WindowManagerImpl
public class WindowManagerImpl implements WindowManager {
......
public void addView(View view, ViewGroup.LayoutParams params)
{
addView(view, params, false);
}
WindowManagerImpl
final WindowManager.LayoutParams wparams
= (WindowManager.LayoutParams)params;
ViewRoot root;
View panelParentView = null;
ViewRoot
private final ArrayList<View> mViews = new ArrayList<View>();
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
private final ArrayList<WindowManager.LayoutParams> mParams =
new ArrayList<WindowManager.LayoutParams>();
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
ViewRootImpl
mViews[index] = view;
mRoots[index] = root;
mParams[index] = wparams;
mViews mRoots mParams
WindowManagerImpl类的三个参数版本的成员函数addView在关联一个View对象、
一个ViewRoot对象和一个WindowManager.LayoutParams对象的时候,
WindowManagerImpl addView View ViewRoot WindowManager.LayoutParams
root.setView(view, wparams, panelParentView);
上述操作执行完成之后,ViewRoot类的成员函数setView就可以将成员变量mAdded的值设置为true了,表示当前正在处理的一个ViewRoot对象已经关联好一个View对象了。接下来,ViewRoot类的成员函数setView还需要执行两个操作:
1. 调用ViewRoot类的另外一个成员函数requestLayout来请求对应用程序窗口视图的UI作第一次布局。
2. 调用ViewRoot类的静态成员变量sWindowSession所描述的一个类型为Session的Binder代理对象的成员函数add来请求WindowManagerService增加一个WindowState对象,以便可以用来描述当前正在处理的一个ViewRoot所关联的一个应用程序窗口。
至此,我们就分析完成Android应用程序窗口视图对象的创建过程了。在接下来的一篇文章中,我们将会继续分析Android应用程序窗口与WindowManagerService服务的连接过程,即Android应用程序窗口请求WindowManagerService为其增加一个WindowState对象的过程,而在接下来的两篇文章中,我们还会分析用来渲染Android应用程序窗口的Surface的创建过程,以及Android应用程序窗口的渲染过程。通过这三个过程的分析,我们就可以看到上述第1点和第2点提到的两个函数的执行过程,敬请期待!
requestLayout();
以便后面可以通过该ViewRoot对象来控制应用程序窗口视图的UI展现。
ViewRoot
本文地址:https://blog.csdn.net/u014644594/article/details/107549103
下一篇: 我在火葬场上班