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

Android Activity启动到组件渲染(一)
上一篇我们说到ActivityThread执行了performLaunchActivity()方法后,回到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();
        }
    }
}

如果加载的Activity正常,则开始执行handleResumeActivity(),接着分析。

final void handleResumeActivity(IBinder token,
        boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
    ActivityClientRecord r = mActivities.get(token);
    ...
    r = performResumeActivity(token, clearHide, reason);
    if (r != null) {
        ...
            r.window = r.activity.getWindow();
            View decor = r.window.getDecorView();
            decor.setVisibility(View.INVISIBLE);
            ViewManager wm = a.getWindowManager();
            ...
            if (a.mVisibleFromClient) {
                if (!a.mWindowAdded) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                } else {
                    ...
                }
       ...
                if (r.activity.mVisibleFromClient) {
                    ViewManager wm = a.getWindowManager();
                    View decor = r.window.getDecorView();
                    wm.updateViewLayout(decor, l);
                }
            ...
            }...
}

第5行的performResumeActivity()方法会调用Activity.onResume()方法。然后从Activity中获取Window,也就是上一篇提到的PhoneWindow,又从Window获取DecorView,最后使用WindowManager.addView将DecorView添加到WindowManager中,这样DecorView就可以在手机屏上被渲染出来了。

WindowManager.addView是如何渲染,我们可以再往下了解一下,这里的WindowManager是Activity.getWindowManager(),发现获取WindowManager是mWindowManager全局变量,它是什么时候定义的呢?

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();
       ...
}

我们可以温故一下,其实上一篇有提到,在attach方法中后半段mWindow.setWindowManager()方法就是初始化WindowManager,具体看一下代码。

  public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
        boolean hardwareAccelerated) {
    ...
    if (wm == null) {
        wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
    }
    mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}

通过getSystemService()方法获取WindowManager的实例,WindowManager是接口,所以通过createLocalWindowManager()方法生成了一个WindowManagerImpl的对象,它是WindowManager的实现类。

public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
        return new WindowManagerImpl(mContext, parentWindow);
    }

我们可以看到Acitivity的wm实际上是一个WindowManagerImpl类型的对象,它的addView方法也在WindowManagerImpl中实现。

private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
@Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
    }

实际上是调用的是WindowManagerGlobal.addView()方法。新建了一个ViewRootImpl对象并调用其setView方法。

public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow) {
    ...
    ViewRootImpl root;
    View panelParentView = null;
    synchronized (mLock) {
    ...
        root = new ViewRootImpl(view.getContext(), display);
        view.setLayoutParams(wparams);
        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);
        // do this last because it fires off messages to start doing things
        try {
            root.setView(view, wparams, panelParentView);
        } catch (RuntimeException e) {
            ...
        }
    }
}

这里有个题外话,ViewRootImpl在调用requestLayout()方法时,会调用checkThread()方法。

void checkThread() {
        if (mThread != Thread.currentThread()) {
            throw new CalledFromWrongThreadException(
                    "Only the original thread that created a view hierarchy can touch its views.");
        }
    }

checkThread()会检查判断当前线程和创建ViewRootImpl的线程是不是同一个线程,如果不是同一个线程,则会抛出CalledFromWrongThreadException异常,这也是为什么不能在子线程操作View的原因,但也不是所有的子线程都不能操作View,在onCreate()方法中新建一个线程也可能不会抛出异常,因为这时候ViewRootImpl还没有创建,当执行onResume时,ViewRootImpl被创建,会进行第一次layout,这个时候才会检查是否在主线程中操作UI。

我们继续分析ViewRootImpl.setView()方法。

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        synchronized (this) {
            if (mView == null) {
                mView = view;
                ...
                requestLayout();
                ...
                try {
                    ...
                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(),
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mInputChannel);
                } catch (RemoteException e) {
                    ...
                } finally {
                    ...
                }
                ...
            }
        }
    }

ViewRootImpl.setView()先调用requestLayout方法绘制View,然后调用mWindowSession.addToDisplay()方法与WMS通信。
ViewRootImpl.java

mWindowSession = WindowManagerGlobal.getWindowSession();

WindowManagerGlobal.java

public static IWindowSession getWindowSession() {
    synchronized (WindowManagerGlobal.class) {
        if (sWindowSession == null) {
            try {
                InputMethodManager imm = InputMethodManager.getInstance();
                IWindowManager windowManager = getWindowManagerService();
                sWindowSession = windowManager.openSession(
                        new IWindowSessionCallback.Stub() {
                            @Override
                            public void onAnimatorScaleChanged(float scale) {
                                ValueAnimator.setDurationScale(scale);
                            }
                        },
                        imm.getClient(), imm.getInputContext());
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        return sWindowSession;
    }
}
public static IWindowManager getWindowManagerService() {
    synchronized (WindowManagerGlobal.class) {
        if (sWindowManagerService == null) {
            sWindowManagerService = IWindowManager.Stub.asInterface(
                    ServiceManager.getService("window"));
            try {
                if (sWindowManagerService != null) {
                    ValueAnimator.setDurationScale(
                            sWindowManagerService.getCurrentAnimatorScale());
                }
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        return sWindowManagerService;
    }
}

WindowManagerService.java

  @Override
    public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
            IInputContext inputContext) {
        if (client == null) throw new IllegalArgumentException("null client");
        if (inputContext == null) throw new IllegalArgumentException("null inputContext");
        Session session = new Session(this, callback, client, inputContext);
        return session;
    }

先获取WindowManagerService的IBinder接口IWindowManager,然后通过调用openSession方法返回一个IWindowSession的对象,它实际的类型时Session类型。
Session.java

final WindowManagerService mService;
public Session(WindowManagerService service, IWindowSessionCallback callback,
        IInputMethodClient client, IInputContext inputContext) {
    mService = service;
    ...
}
@Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
        int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
        Rect outOutsets, InputChannel outInputChannel) {
    return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
            outContentInsets, outStableInsets, outOutsets, outInputChannel);
}

实际上调用Session.addToDisplay方法,最后还是调用的WMS中的addWindow方法。

总结

handleResumeActivity方法中调用了ActivityThread在attach方法中生成的WindowManager.addView方法,它实际上是在WindowManagerGlobal新建了一个ViewRootImpl对象,并使用该对象绘制真正的view,最后与WMS通信让其在屏幕上渲染出来。

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

猜你喜欢

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