欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

Android应用程序窗口(Activity,Window,View)原理解析

程序员文章站 2022-03-21 18:53:25
Android应用程序窗口(Activity)的运行上下文环境(Context)的创建过程分析ActivityThreadpublic final class ActivityThread { private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { activity = mInstrumentation.newActivity( ......

    1. Android应用程序启动过程的源代码分析;

        2. Android应用程序内部启动Activity过程(startActivity)的源代码分析。

 

Android应用程序窗口(Activity,Window,View)原理解析

 

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,View)原理解析

 

Android应用程序窗口(Activity,Window,View)原理解析

 

 Android应用程序窗口(Activity,Window,View)原理解析

        
        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,Window,View)原理解析

 

Android应用程序窗口(Activity,Window,View)原理解析

Android应用程序窗口(Activity)的视图对象(View)的创建过程分析

Android应用程序窗口(Activity,Window,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

相关标签: framework