SystemUI 学习(2) — StatusBar
StatusBar的创立进程
在SystemUI 学习(1)
中已经了解了SystemUI
发动的进程,而在SystemUI
发动进程中,体系会发动相关的服务组件,其间当然就包含了StatusBar
。
注:
StatusBars
的发动在Android11版本进行了改动,Android10存在一个SystemBars.java
类,在这个类里进行获取StatusBars
的资源并发动它。而在Android11往后,这个类被移除了。而
StatusBar
则由SystemUI
程序直接发动。在第一篇
SystemUi
学习文档中说到过,在体系第一次发动SystemUI
时,SystemUI
会发动许多服务组件。其间就包含了StatusBar
,而Android11
以前是SystemBars
代替的StatusBars
。
状态栏视图窗口的创立剖析(Start办法)
-
StatusBar
的start()
办法frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
public class StatusBar extends SystemUI implements ActivityStarter, LifecycleOwner { @Override public void start() { //...代码省掉... createAndAddWindows(result); //...代码省掉... } }
start
办法会调用一个叫createAndAddWindows
的要害办法,体系状态栏视图的创立和增加工作就是在该办法中完成的。StatusBar start
之后开始新建增加和填充视图。 -
与
createAndAddWindows
相关的代码public class StatusBar extends SystemUI implements /*代码省掉*/ { //...代码省掉... private final StatusBarWindowController mStatusBarWindowController; private final StatusBarComponent.Factory mStatusBarComponentFactory; private StatusBarComponent mStatusBarComponent; //...代码省掉... public StatusBar( //...代码省掉... StatusBarWindowController statusBarWindowController, StatusBarComponent.Factory statusBarComponentFactory, //...代码省掉... ){ //...代码省掉... mStatusBarWindowController = statusBarWindowController;//状态栏控制器 mStatusBarComponentFactory = statusBarComponentFactory; //...代码省掉... } @Override public void start() { //...代码省掉... createAndAddWindows(result); //...代码省掉... } public void createAndAddWindows(@Nullable RegisterStatusBarResult result) { makeStatusBarView(result); //...代码省掉... mStatusBarWindowController.attach(); } protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) { //...代码省掉... inflateStatusBarWindow(); //...代码省掉... mStatusBarWindowController.getFragmentHostManager() .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {/*代码省掉*/}) .getFragmentManager() .beginTransaction() .replace(R.id.status_bar_container, mStatusBarComponent.createCollapsedStatusBarFragment(), CollapsedStatusBarFragment.TAG) .commit(); //...代码省掉... } private void inflateStatusBarWindow() { mStatusBarComponent = mStatusBarComponentFactory.create(); //...代码省掉... } }
createAndAddWindows
首要调用了makeStatusBarView
办法来构建视图,makeStatusBarView办法又会调用inflateStatusBarWindow
办法,inflateStatusBarWindow办法内部又调用mStatusBarComponentFactory
的create办法为状态栏组件mStatusBarComponent
赋值。在inflateStatusBarWindow办法执行完毕后,makeStatusBarView办法会调用
mStatusBarWindowController
的getFragmentHostManager来获取FragmentHostManager
目标实例。 -
上面说到一个办法—–
StatusBarWindowController
的getFragmentHostManager办法,相关代码。frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@SysUISingleton public class StatusBarWindowController { @Inject public StatusBarWindowController( Context context, @StatusBarWindowModule.InternalWindowView StatusBarWindowView statusBarWindowView, WindowManager windowManager, IWindowManager iWindowManager, StatusBarContentInsetsProvider contentInsetsProvider, @Main Resources resources) { //...代码省掉... mStatusBarWindowView = statusBarWindowView; //...代码省掉... } public FragmentHostManager getFragmentHostManager() { return FragmentHostManager.get(mStatusBarWindowView); } }
getFragmentHostManager
内部会将mStatusBarWindowView
作为唯一参数,持续调用FragmentHostManager
的get办法。 -
持续检查
FragmentHostManager
的get办法代码frameworks/base/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
public class FragmentHostManager { public static FragmentHostManager get(View view) { try { return Dependency.get(FragmentService.class).getFragmentHostManager(view); } catch (ClassCastException e) { // TODO: Some auto handling here? throw e; } } }
-
get办法调用了
FragmentService
的getFragmentHostManager办法frameworks/base/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
public class FragmentService implements Dumpable { public FragmentHostManager getFragmentHostManager(View view) { View root = view.getRootView(); FragmentHostState state = mHosts.get(root); if (state == null) { //创立FragmentHostState目标实例 state = new FragmentHostState(root); mHosts.put(root, state); } //调用FragmentHostState的getFragmentHostManager办法 return state.getFragmentHostManager(); } private class FragmentHostState { private final View mView; private FragmentHostManager mFragmentHostManager; public FragmentHostState(View view) { mView = view; //创立FragmentHostManager目标实例 mFragmentHostManager = new FragmentHostManager(FragmentService.this, mView); } public FragmentHostManager getFragmentHostManager() { return mFragmentHostManager; } } }
回来检查
FragmentHostManager
相关代码public class FragmentHostManager { private final View mRootView; FragmentHostManager(FragmentService manager, View rootView) { //...代码省掉... //将StatusBarWindowView赋值给mRootView mRootView = rootView; //...代码省掉... }
FragmentService
的getFragmentHostManager会创立FragmentHostState
目标实例,然后调用该目标的getFragmentHostManager办法,该办法会回来mFragmentHostManager
,而mFragmentHostManager
最早是在FragmentHostState
自己的结构办法中创立的,本来绕了一圈,最后得到的结果其实就是,StatusBarWindowController
的getFragmentHostManager办法会将StatusBarWindowView
作为结构办法参数创立FragmentHostManager
实例目标。 -
关注到
mStatusBarWindowView
目标作为参数在各种办法中传递,探究一下具体来源。获取StatusBarWindowView
目标实例的要害代码坐落StatusBarWindowModule.kt
的providesStatusBarWindowView办法中frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt
@Module abstract class StatusBarWindowModule { @Module companion object { //供给一个单例的StatusBarWindowView目标实例 @JvmStatic @Provides @SysUISingleton @InternalWindowView fun providesStatusBarWindowView(layoutInflater: LayoutInflater): StatusBarWindowView { return layoutInflater.inflate( R.layout.super_status_bar, /* root= */null ) as StatusBarWindowView? ?: throw IllegalStateException( "R.layout.super_status_bar could not be properly inflated" ) } } }
-
在providesStatusBarWindowView办法中,
StatusBarWindowView
是直接使用R.layout.super_status_bar
布局文件转化成View
目标的。frameworks/base/packages/SystemUI/res/layout/super_status_bar.xml
<com.android.systemui.statusbar.window.StatusBarWindowView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:sysui="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <FrameLayout android:id="@+id/status_bar_launch_animation_container" android:layout_width="match_parent" android:layout_height="match_parent" /> <FrameLayout android:id="@+id/status_bar_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/system_bar_background" /> </com.android.systemui.statusbar.window.StatusBarWindowView>
将状态栏窗口增加到Window中
-
StatusBar
的createAndAddWindows
办法在调用makeStatusBarView
办法构建好状态栏视图之后,便会调用StatusBarWindowController
的attach
办法。 -
StatusBarWindowController的attach办法。
@SysUISingleton public class StatusBarWindowController { private final WindowManager mWindowManager; private WindowManager.LayoutParams mLp; @Inject public StatusBarWindowController( Context context, @StatusBarWindowModule.InternalWindowView StatusBarWindowView statusBarWindowView, WindowManager windowManager, IWindowManager iWindowManager, StatusBarContentInsetsProvider contentInsetsProvider, @Main Resources resources) { //...代码省掉... mWindowManager = windowManager; mStatusBarWindowView = statusBarWindowView; if (mBarHeight < 0) { mBarHeight = SystemBarUtils.getStatusBarHeight(mContext); } } public void attach() { //获取状态栏类型窗口所需求的布局参数 mLp = getBarLayoutParams(mContext.getDisplay().getRotation()); //调用WindowManager的addView办法将状态栏窗口增加到Window中。 mWindowManager.addView(mStatusBarWindowView, mLp); //...代码省掉... } }
-
attach
首要调用getBarLayoutParams
办法获取状态栏类型窗口所需求的布局参数,在获取到状态栏视图所需的参数后便会调用WindowManager
的addView办法将状态栏视图窗口增加到Window
中。注:StatusBar源码在Android11、Android12.0、Android12.1和Android13都存在一定的差异,本文以Android12.1代码作剖析,其它版本源码或许存在差异,但是剖析办法相同。感兴趣的能够自己去源码网站看看
当然在StatusBar中还有和告诉栏、底部导航栏的相关代码,这个咱们后面再做剖析
总结
SystemUI发动后,会经过资源文件发动相关的组件服务,其间就包含了StatusBar。StatusBar发动后,在start()办法中创立和增加窗口,然后构建StatusBar
视图、填充StatusBar
视图。然后实例化StatusBarWindowController
,再经过StatusBarWindowController
增加视图给WindowManager。
参阅文章:体系状态栏StatusBar的创立流程 源码网站:Android Code Search 版本android-12.1.0_r8