上一篇我们具体分析了SystemUI的启动流程,在SystemServer的startOtherServices方法中,会启动SystemUIService服务,SystemUIService服务的onCreate方法会继续调用SystemUIApplication的startServicesIfNeeded方法,在该方法中会获取SystemUI组件各个类的具体路径,并通过和dagger2相关的ComponentHelper关键接口,获取SystemUI组件对应的实例对象,然后依次调用每个组件的start() 方法启动相关类的服务,启动完成后,又会再次调用该组件的onBootCompleted( ) 方法。
frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
private void startServicesIfNeeded(String metricsPrefix, String[] services) {
if (mServicesStarted) {//如果服务已经启动直接返回
return;
}
mServices = new SystemUI[services.length];
...代码省略...
final int N = services.length;
for (int i = 0; i < N; i++) {
String clsName = services[i];//具体SystemUI组件类的完整路径
long ti = System.currentTimeMillis();
try {
SystemUI obj = mComponentHelper.resolveSystemUI(clsName);//ComponentHelper的resolveSystemUI方法可以通过类名拿到具体的SystemUI实例对象
if (obj == null) {//如果通过ComponentHelper的resolveSystemUI没有成功获取到实例对象,则通过反射创建,代码基本上不会走这里。
Constructor constructor = Class.forName(clsName).getConstructor(Context.class);
obj = (SystemUI) constructor.newInstance(this);//通过反射创建实例对象
}
mServices[i] = obj;//将获取的obj实例对象赋值到数组中。
} catch (ClassNotFoundException
| NoSuchMethodException
| IllegalAccessException
| InstantiationException
| InvocationTargetException ex) {
throw new RuntimeException(ex);
}
...代码省略...
mServices[i].start();
...代码省略...
if (mBootCompleteCache.isBootComplete()) {
mServices[i].onBootCompleted();
}
...代码省略...
}
...代码省略...
mServicesStarted = true;//服务已经被启动
}
frameworks/base/packages/SystemUI/res/values/config.xml
<string-array name="config_systemUIServiceComponents" translatable="false">
<item>com.android.systemui.util.NotificationChannels</item><!--通知-->
<item>com.android.systemui.keyguard.KeyguardViewMediator</item><!--键盘锁状态-->
<item>com.android.systemui.recents.Recents</item><!--任务列表-->
<item>com.android.systemui.volume.VolumeUI</item><!--监听音量,并决定是否显示音量的对话框-->
<item>com.android.systemui.statusbar.phone.StatusBar</item><!--状态栏-->
<item>com.android.systemui.usb.StorageNotification</item><!--监听 USB 连接状态并发送通知进行提示-->
<item>com.android.systemui.power.PowerUI</item><!--监听电量状态并在低电量时发送通知-->
<item>com.android.systemui.media.RingtonePlayer</item><!--用于播放铃声-->
<item>com.android.systemui.keyboard.KeyboardUI</item><!--键盘锁 UI-->
<item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item><!--快捷分发器-->
<item>@string/config_systemUIVendorServiceComponent</item><!--这里可以定义厂商定制的组件-->
<item>com.android.systemui.util.leak.GarbageMonitor$Service</item><!--用于监控内存泄漏的服务-->
<item>com.android.systemui.LatencyTester</item><!--仅在 debug 环境执行,用于监听系统测试延迟的模拟动作-->
<item>com.android.systemui.globalactions.GlobalActionsComponent</item><!--用于显示全局对话框(例如长按电源按键)-->
<item>com.android.systemui.ScreenDecorations</item><!--处理页面中的显示的形状(如圆角)-->
<item>com.android.systemui.biometrics.AuthController</item><!--身份验证-->
<item>com.android.systemui.SliceBroadcastRelayHandler</item><!--允许打开设置App-->
<item>com.android.systemui.statusbar.notification.InstantAppNotifier</item><!--时应用程序通知-->
<item>com.android.systemui.theme.ThemeOverlayController</item><!--主题-->
<item>com.android.systemui.accessibility.WindowMagnification</item><!--放大器-->
<item>com.android.systemui.accessibility.SystemActions</item>
<item>com.android.systemui.toast.ToastUI</item>
<item>com.android.systemui.wmshell.WMShell</item>
</string-array>
本篇文章我们主要来分析一下com.android.systemui.statusbar.phone.StatusBar所对应的状态栏类的创建过程。
1、通过前面的分析我们知道,SystemUI的所有组件实例都是通过和dagger2相关的ComponentHelper类得到的,该类中的的SystemUI组件实例最初是通过dagger2的依赖注入得到的,而dagger2在实例化SystemUI组件的时候,会调用对应组件的构造方法,StatusBar的构造方法如下所示:
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
public class StatusBar extends SystemUI implements ActivityStarter, LifecycleOwner {
public StatusBar(
Context context,
NotificationsController notificationsController,
FragmentService fragmentService,
LightBarController lightBarController,
AutoHideController autoHideController,
StatusBarWindowController statusBarWindowController,//状态栏控制器
KeyguardUpdateMonitor keyguardUpdateMonitor,
StatusBarSignalPolicy statusBarSignalPolicy,
PulseExpansionHandler pulseExpansionHandler,
NotificationWakeUpCoordinator notificationWakeUpCoordinator,
KeyguardBypassController keyguardBypassController,
KeyguardStateController keyguardStateController,
HeadsUpManagerPhone headsUpManagerPhone,
DynamicPrivacyController dynamicPrivacyController,
BypassHeadsUpNotifier bypassHeadsUpNotifier,
FalsingManager falsingManager,
FalsingCollector falsingCollector,
BroadcastDispatcher broadcastDispatcher,
NotifShadeEventSource notifShadeEventSource,
NotificationEntryManager notificationEntryManager,
NotificationGutsManager notificationGutsManager,
NotificationLogger notificationLogger,
NotificationInterruptStateProvider notificationInterruptStateProvider,
NotificationViewHierarchyManager notificationViewHierarchyManager,
PanelExpansionStateManager panelExpansionStateManager,
KeyguardViewMediator keyguardViewMediator,
DisplayMetrics displayMetrics,
MetricsLogger metricsLogger,
@UiBackground Executor uiBgExecutor,
NotificationMediaManager notificationMediaManager,
NotificationLockscreenUserManager lockScreenUserManager,
NotificationRemoteInputManager remoteInputManager,
UserSwitcherController userSwitcherController,
NetworkController networkController,
BatteryController batteryController,
SysuiColorExtractor colorExtractor,
ScreenLifecycle screenLifecycle,
WakefulnessLifecycle wakefulnessLifecycle,
SysuiStatusBarStateController statusBarStateController,
Optional<BubblesManager> bubblesManagerOptional,
Optional<Bubbles> bubblesOptional,
VisualStabilityManager visualStabilityManager,
DeviceProvisionedController deviceProvisionedController,
NavigationBarController navigationBarController,
AccessibilityFloatingMenuController accessibilityFloatingMenuController,
Lazy<AssistManager> assistManagerLazy,
ConfigurationController configurationController,
NotificationShadeWindowController notificationShadeWindowController,
DozeParameters dozeParameters,
ScrimController scrimController,
Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
LockscreenGestureLogger lockscreenGestureLogger,
Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
DozeServiceHost dozeServiceHost,
PowerManager powerManager,
ScreenPinningRequest screenPinningRequest,
DozeScrimController dozeScrimController,
VolumeComponent volumeComponent,
CommandQueue commandQueue,
CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger,
StatusBarComponent.Factory statusBarComponentFactory,//状态栏组件工厂
PluginManager pluginManager,
Optional<LegacySplitScreen> splitScreenOptional,
LightsOutNotifController lightsOutNotifController,
StatusBarNotificationActivityStarter.Builder
statusBarNotificationActivityStarterBuilder,
ShadeController shadeController,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
ViewMediatorCallback viewMediatorCallback,
InitController initController,
@Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler,
PluginDependencyProvider pluginDependencyProvider,
KeyguardDismissUtil keyguardDismissUtil,
ExtensionController extensionController,
UserInfoControllerImpl userInfoControllerImpl,
OperatorNameViewController.Factory operatorNameViewControllerFactory,
PhoneStatusBarPolicy phoneStatusBarPolicy,
KeyguardIndicationController keyguardIndicationController,
DemoModeController demoModeController,
Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy,
StatusBarTouchableRegionManager statusBarTouchableRegionManager,
NotificationIconAreaController notificationIconAreaController,
BrightnessSliderController.Factory brightnessSliderFactory,
WallpaperController wallpaperController,
OngoingCallController ongoingCallController,
SystemStatusAnimationScheduler animationScheduler,
StatusBarLocationPublisher locationPublisher,
StatusBarIconController statusBarIconController,
StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,
LockscreenShadeTransitionController lockscreenShadeTransitionController,
FeatureFlags featureFlags,
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
@Main Handler mainHandler,
@Main DelayableExecutor delayableExecutor,
@Main MessageRouter messageRouter,
WallpaperManager wallpaperManager,
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
Optional<StartingSurface> startingSurfaceOptional,
TunerService tunerService,
DumpManager dumpManager,
ActivityLaunchAnimator activityLaunchAnimator) {
super(context);
mNotificationsController = notificationsController;
mFragmentService = fragmentService;
mLightBarController = lightBarController;
mAutoHideController = autoHideController;
mStatusBarWindowController = statusBarWindowController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mPulseExpansionHandler = pulseExpansionHandler;
mWakeUpCoordinator = notificationWakeUpCoordinator;
mKeyguardBypassController = keyguardBypassController;
mKeyguardStateController = keyguardStateController;
mHeadsUpManager = headsUpManagerPhone;
mOperatorNameViewControllerFactory = operatorNameViewControllerFactory;
mKeyguardIndicationController = keyguardIndicationController;
mStatusBarTouchableRegionManager = statusBarTouchableRegionManager;
mDynamicPrivacyController = dynamicPrivacyController;
mBypassHeadsUpNotifier = bypassHeadsUpNotifier;
mFalsingCollector = falsingCollector;
mFalsingManager = falsingManager;
mBroadcastDispatcher = broadcastDispatcher;
mNotifShadeEventSource = notifShadeEventSource;
mEntryManager = notificationEntryManager;
mGutsManager = notificationGutsManager;
mNotificationLogger = notificationLogger;
mNotificationInterruptStateProvider = notificationInterruptStateProvider;
mViewHierarchyManager = notificationViewHierarchyManager;
mPanelExpansionStateManager = panelExpansionStateManager;
mKeyguardViewMediator = keyguardViewMediator;
mDisplayMetrics = displayMetrics;
mMetricsLogger = metricsLogger;
mUiBgExecutor = uiBgExecutor;
mMediaManager = notificationMediaManager;
mLockscreenUserManager = lockScreenUserManager;
mRemoteInputManager = remoteInputManager;
mUserSwitcherController = userSwitcherController;
mNetworkController = networkController;
mBatteryController = batteryController;
mColorExtractor = colorExtractor;
mScreenLifecycle = screenLifecycle;
mWakefulnessLifecycle = wakefulnessLifecycle;
mStatusBarStateController = statusBarStateController;
mBubblesManagerOptional = bubblesManagerOptional;
mBubblesOptional = bubblesOptional;
mVisualStabilityManager = visualStabilityManager;
mDeviceProvisionedController = deviceProvisionedController;
mNavigationBarController = navigationBarController;
mAccessibilityFloatingMenuController = accessibilityFloatingMenuController;
mAssistManagerLazy = assistManagerLazy;
mConfigurationController = configurationController;
mNotificationShadeWindowController = notificationShadeWindowController;
mDozeServiceHost = dozeServiceHost;
mPowerManager = powerManager;
mDozeParameters = dozeParameters;
mScrimController = scrimController;
mLockscreenWallpaperLazy = lockscreenWallpaperLazy;
mLockscreenGestureLogger = lockscreenGestureLogger;
mScreenPinningRequest = screenPinningRequest;
mDozeScrimController = dozeScrimController;
mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
mNotificationShadeDepthControllerLazy = notificationShadeDepthControllerLazy;
mVolumeComponent = volumeComponent;
mCommandQueue = commandQueue;
mCollapsedStatusBarFragmentLogger = collapsedStatusBarFragmentLogger;
mStatusBarComponentFactory = statusBarComponentFactory;
mPluginManager = pluginManager;
mSplitScreenOptional = splitScreenOptional;
mStatusBarNotificationActivityStarterBuilder = statusBarNotificationActivityStarterBuilder;
mShadeController = shadeController;
mLightsOutNotifController = lightsOutNotifController;
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
mKeyguardViewMediatorCallback = viewMediatorCallback;
mInitController = initController;
mPluginDependencyProvider = pluginDependencyProvider;
mKeyguardDismissUtil = keyguardDismissUtil;
mExtensionController = extensionController;
mUserInfoControllerImpl = userInfoControllerImpl;
mIconPolicy = phoneStatusBarPolicy;
mDemoModeController = demoModeController;
mNotificationIconAreaController = notificationIconAreaController;
mBrightnessSliderFactory = brightnessSliderFactory;
mWallpaperController = wallpaperController;
mOngoingCallController = ongoingCallController;
mAnimationScheduler = animationScheduler;
mStatusBarSignalPolicy = statusBarSignalPolicy;
mStatusBarLocationPublisher = locationPublisher;
mStatusBarIconController = statusBarIconController;
mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager;
mFeatureFlags = featureFlags;
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
mMainHandler = mainHandler;
mMainExecutor = delayableExecutor;
mMessageRouter = messageRouter;
mWallpaperManager = wallpaperManager;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
mTunerService = tunerService;
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
mStartingSurfaceOptional = startingSurfaceOptional;
lockscreenShadeTransitionController.setStatusbar(this);
mPanelExpansionStateManager.addExpansionListener(this::onPanelExpansionChanged);
mBubbleExpandListener =
(isExpanding, key) -> mContext.getMainExecutor().execute(() -> {
mNotificationsController.requestNotificationUpdate("onBubbleExpandChanged");
updateScrimController();
});
mActivityIntentHelper = new ActivityIntentHelper(mContext);
mActivityLaunchAnimator = activityLaunchAnimator;
// The status bar background may need updating when the ongoing call status changes.
mOngoingCallController.addCallback((animate) -> maybeUpdateBarMode());
// TODO(b/190746471): Find a better home for this.
DateTimeView.setReceiverHandler(timeTickHandler);
mMessageRouter.subscribeTo(KeyboardShortcutsMessage.class,
data -> toggleKeyboardShortcuts(data.mDeviceId));
mMessageRouter.subscribeTo(MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU,
id -> dismissKeyboardShortcuts());
mMessageRouter.subscribeTo(AnimateExpandSettingsPanelMessage.class,
data -> mCommandQueueCallbacks.animateExpandSettingsPanel(data.mSubpanel));
mMessageRouter.subscribeTo(MSG_LAUNCH_TRANSITION_TIMEOUT,
id -> onLaunchTransitionTimeout());
}
}
StatusBar的构造方法乍一看简直恐怖如斯,因为它的参数居然足足有100多个,这种代码要是放在以前,肯定妥妥的被骂翻!构造方法参数如此之多别人要如何创建对象实例?幸好现在有了Dagger2框架的加持,该框架会自动帮我们创建对象实例并传入StatusBar需要的所有参数,我们直接在StatusBar中用就是了,所以构造方法就算有再多参数也不是什么大问题了。
1、结合前面SystemUIApplication的startServicesIfNeeded方法我们知道,在获得每个SystemUI组件对象之后,都会调用该对象的start方法,作为SystemUI组件之一的StatusBar自然也不例外:
public class StatusBar extends SystemUI implements ActivityStarter, LifecycleOwner {
@Override
public void start() {
...代码省略...
createAndAddWindows(result);
...代码省略...
}
}
start方法会调用一个叫createAndAddWindows的关键方法,系统状态栏视图的创建和添加工作就是在该方法中完成的。
2、和createAndAddWindows方法相关的代码如下所示:
public class StatusBar extends SystemUI implements ActivityStarter, LifecycleOwner {
private final StatusBarWindowController mStatusBarWindowController;//状态栏窗口控制器
private final StatusBarComponent.Factory mStatusBarComponentFactory;//Dagger2状态栏组件工厂
private StatusBarComponent mStatusBarComponent;//Dagger2状态栏子组件
protected PhoneStatusBarView mStatusBarView;//状态栏视图
private PhoneStatusBarViewController mPhoneStatusBarViewController;//状态栏视图控制器
public StatusBar(
...代码省略...
StatusBarWindowController statusBarWindowController,//状态栏控制器
StatusBarComponent.Factory statusBarComponentFactory,//状态栏Dagger2组件工厂
...代码省略...
){
...代码省略...
//为状态栏控制器mStatusBarWindowController赋值
mStatusBarWindowController = statusBarWindowController;
//为状态栏Dagger2组件工厂mStatusBarComponentFactory赋值
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();
...代码省略...
}
}
1)StatusBar的构造方法会为状态栏窗口控制器mStatusBarWindowController和Dagger2状态栏组件工厂mStatusBarComponentFactory对象赋值。createAndAddWindows首先调用了makeStatusBarView方法来构建视图,makeStatusBarView方法又会调用inflateStatusBarWindow方法,inflateStatusBarWindow方法内部又调用mStatusBarComponentFactory的create方法为Dagger2状态栏组件mStatusBarComponent赋值。等inflateStatusBarWindow方法执行完毕,makeStatusBarView方法会调用mStatusBarWindowController的getFragmentHostManager来获取FragmentHostManager对象实例。
2)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方法。
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;
}
}
}
FragmentHostManager的get方法继续调用FragmentService的getFragmentHostManager方法。
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;
}
}
}
FragmentService的getFragmentHostManager会创建FragmentHostState对象实例,然后调用该对象的getFragmentHostManager方法,该方法会返回mFragmentHostManager,而mFragmentHostManager最早是在FragmentHostState自己的构造方法中创建的,原来绕了一圈,最后得到的结果其实就是,StatusBarWindowController的getFragmentHostManager方法会将StatusBarWindowView作为构造方法参数创建FragmentHostManager实例对象。
public class FragmentHostManager {
private final View mRootView;
FragmentHostManager(FragmentService manager, View rootView) {
...代码省略...
//将StatusBarWindowView赋值给mRootView
mRootView = rootView;
...代码省略...
}
由于后续会用到mRootView,这里我们就有必要看一下StatusBarWindowView的来源了,因为需要知道其对应的布局文件。
3)StatusBarWindowController最早是被dagger2依赖注入到StatusBar中的,作为构造方法参数的StatusBarWindowView,也是被Dagger2依赖注入到StatusBarWindowController中的。Dagger2获取StatusBarWindowView对象实例的关键代码位于StatusBarWindowModule的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直接将super_status_bar.xml布局文件转化为View对象,然后再将View转化为StatusBarWindowView进行返回,其中的super_status_bar.xml布局文件内容如下所示:
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>
根控件是StatusBarWindowView,正是我们之前多次提到的状态栏窗口对象,其内部有两个FrameLayout,id为status_bar_launch_animation_container的FrameLayout主要是负责状态栏打开其他Activity时候的切换动画,id为status_bar_container的FrameLayout则是承载状态栏视图内容的容器。
1、继续来看在StatusBar的makeStatusBarView方法。
protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
...代码省略...
mStatusBarWindowController.getFragmentHostManager()
.addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {代码省略})
.getFragmentManager()
.beginTransaction()
.replace(R.id.status_bar_container,
mStatusBarComponent.createCollapsedStatusBarFragment(),
CollapsedStatusBarFragment.TAG)
.commit();
...代码省略...
}
在调用StatusBarWindowController的getFragmentHostManager获得FragmentHostManager实例对象之后,会继续调用addTagListener方法设置监听对象,然后获取FragmentManager并开启会话,再调用mStatusBarComponent的createCollapsedStatusBarFragment方法创建状态栏视图的CollapsedStatusBarFragment,将其对应的视图设置到id为status_bar_container的控件上。
2、StatusBarComponent和创建CollapsedStatusBarFragment对象实例有关的代码如下所示:
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java
@Subcomponent(modules = {StatusBarViewModule.class})
@StatusBarComponent.StatusBarScope
public interface StatusBarComponent {
/**
* Builder for {@link StatusBarComponent}.
*/
@Subcomponent.Factory
interface Factory {
StatusBarComponent create();
}
/**
* Scope annotation for singleton items within the StatusBarComponent.
*/
@Documented
@Retention(RUNTIME)
@Scope
@interface StatusBarScope {}
/**
* 每次被调用的时候会创建一个新的CollapsedStatusBarFragment实例对象
*/
CollapsedStatusBarFragment createCollapsedStatusBarFragment();
}
对java来说StatusBarComponent是一个接口,其内部的Factory对应了我们前面提到的状态栏组件工厂mStatusBarComponentFactory;而对于dagger2来说,StatusBarComponent是一个子连接器,且存在一个模块StatusBarViewModule。
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
@Module(subcomponents = StatusBarFragmentComponent.class)
public abstract class StatusBarViewModule {
public static CollapsedStatusBarFragment createCollapsedStatusBarFragment(
StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory,
OngoingCallController ongoingCallController,
SystemStatusAnimationScheduler animationScheduler,
StatusBarLocationPublisher locationPublisher,
NotificationIconAreaController notificationIconAreaController,
PanelExpansionStateManager panelExpansionStateManager,
FeatureFlags featureFlags,
StatusBarIconController statusBarIconController,
StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,
KeyguardStateController keyguardStateController,
NotificationPanelViewController notificationPanelViewController,
NetworkController networkController,
StatusBarStateController statusBarStateController,
CommandQueue commandQueue,
CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger,
OperatorNameViewController.Factory operatorNameViewControllerFactory,
SecureSettings secureSettings,
@Main Executor mainExecutor
) {
return new CollapsedStatusBarFragment(statusBarFragmentComponentFactory,
ongoingCallController,
animationScheduler,
locationPublisher,
notificationIconAreaController,
panelExpansionStateManager,
featureFlags,
statusBarIconController,
statusBarHideIconsForBouncerManager,
keyguardStateController,
notificationPanelViewController,
networkController,
statusBarStateController,
commandQueue,
collapsedStatusBarFragmentLogger,
operatorNameViewControllerFactory,
secureSettings,
mainExecutor);
}
}
在StatusBarViewModule的createCollapsedStatusBarFragment方法内部创建了CollapsedStatusBarFragment对象实例,StatusBarComponent的createCollapsedStatusBarFragment最终触发的其实就是这个方法。
3、前面提到FragmentHostManager有调用addTagListener方法为设置监听对象,该监听对象的回调方法会在CollapsedStatusBarFragment的onViewCreated方法执行之后被调用。
protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
...代码省略...
mStatusBarWindowController.getFragmentHostManager()
.addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
StatusBarFragmentComponent statusBarFragmentComponent =
((CollapsedStatusBarFragment) fragment).getStatusBarFragmentComponent();
if (statusBarFragmentComponent == null) {
throw new IllegalStateException(
"CollapsedStatusBarFragment should have a valid component");
}
//状态栏视图
mStatusBarView = statusBarFragmentComponent.getPhoneStatusBarView();
//状态栏视图控制器
mPhoneStatusBarViewController =
statusBarFragmentComponent.getPhoneStatusBarViewController();
mNotificationPanelViewController.updatePanelExpansionAndVisibility();
setBouncerShowingForStatusBarComponents(mBouncerShowing);
mLightsOutNotifController.setLightsOutNotifView(
mStatusBarView.findViewById(R.id.notification_lights_out));
//为通知栏遮罩窗口控制器设置状态栏
mNotificationShadeWindowViewController.setStatusBarView(mStatusBarView);
checkBarModes();
})
.getFragmentManager()
.beginTransaction()
.replace(R.id.status_bar_container,
mStatusBarComponent.createCollapsedStatusBarFragment(),
CollapsedStatusBarFragment.TAG)
.commit();
...代码省略...
}
回调方法中首先将状态栏视图保存到mStatusBarView中,状态栏视图控制器保存到mPhoneStatusBarViewController 中,然后让状态栏视图和通知栏相关的类进行了一定的关联。
1、CollapsedStatusBarFragment的代码很多,我们这里只讲一下它初始化布局文件的代码。
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
public class CollapsedStatusBarFragment extends Fragment implements CommandQueue.Callbacks,
StatusBarStateController.StateListener,
SystemStatusAnimationCallback {
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.status_bar, container, false);
}
}
可以看到状态栏视图所对应的布局文件为status_bar.xml,该布局文件对应了系统状态栏所的视图内容。
frameworks/base/packages/SystemUI/res/layout/status_bar.xml
<com.android.systemui.statusbar.phone.PhoneStatusBarView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
android:layout_width="match_parent"
android:layout_height="@dimen/status_bar_height"
android:id="@+id/status_bar"
android:orientation="vertical"
android:focusable="false"
android:descendantFocusability="afterDescendants"
android:accessibilityPaneTitle="@string/status_bar"
>
<!--是否有新通知的标志-->
<ImageView
android:id="@+id/notification_lights_out"
android:layout_width="@dimen/status_bar_icon_size"
android:layout_height="match_parent"
android:paddingStart="@dimen/status_bar_padding_start"
android:paddingBottom="2dip"
android:src="@drawable/ic_sysbar_lights_out_dot_small"
android:scaleType="center"
android:visibility="gone"
/>
<!--状态栏视图-->
<LinearLayout android:id="@+id/status_bar_contents"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="@dimen/status_bar_padding_start"
android:paddingEnd="@dimen/status_bar_padding_end"
android:paddingTop="@dimen/status_bar_padding_top"
android:orientation="horizontal"
>
<FrameLayout
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="1">
<include layout="@layout/heads_up_status_bar_layout" />
<!-- The alpha of the left side is controlled by PhoneStatusBarTransitions, and the
individual views are controlled by StatusBarManager disable flags DISABLE_CLOCK and
DISABLE_NOTIFICATION_ICONS, respectively -->
<LinearLayout
android:id="@+id/status_bar_left_side"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:clipChildren="false"
>
<!--延时启动,设备用户名称-->
<ViewStub
android:id="@+id/operator_name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout="@layout/operator_name" />
<!--时钟-->
<com.android.systemui.statusbar.policy.Clock
android:id="@+id/clock"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textAppearance="@style/TextAppearance.StatusBar.Clock"
android:singleLine="true"
android:paddingStart="@dimen/status_bar_left_clock_starting_padding"
android:paddingEnd="@dimen/status_bar_left_clock_end_padding"
android:gravity="center_vertical|start"
/>
<!--正在进行的电话-->
<include layout="@layout/ongoing_call_chip" />
<!--下拉通知页面图标区域-->
<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
android:id="@+id/notification_icon_area"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal"
android:clipChildren="false"/>
</LinearLayout>
</FrameLayout>
<!-- Space should cover the notch (if it exists) and let other views lay out around it -->
<android.widget.Space
android:id="@+id/cutout_space_view"
android:layout_width="0dp"
android:layout_height="match_parent"
android:gravity="center_horizontal|center_vertical"
/>
<!--下拉通知页面的中心图标区域-->
<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
android:id="@+id/centered_icon_area"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal"
android:clipChildren="false"
android:gravity="center_horizontal|center_vertical"/>
<!--状态栏系统图标区域-->
<com.android.keyguard.AlphaOptimizedLinearLayout
android:id="@+id/system_icon_area"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal"
android:gravity="center_vertical|end"
>
<!--系统图标-->
<include layout="@layout/system_icons" />
</com.android.keyguard.AlphaOptimizedLinearLayout>
</LinearLayout>
<!--延迟加载 紧急电话文字-->
<ViewStub
android:id="@+id/emergency_cryptkeeper_text"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout="@layout/emergency_cryptkeeper_text"
/>
</com.android.systemui.statusbar.phone.PhoneStatusBarView>
1)根控件是PhoneStatusBarView,其内部包含了状态栏的所有视图内容,大致结构如下所示。

2)下面是HierarchyViewer关于系统状态栏的一张视图结构分析图,基本可以对应上status_bar.xml布局文件。

1、StatusBar的createAndAddWindows方法在调用makeStatusBarView方法构建好状态栏视图之后,便会调用StatusBarWindowController的attach方法。
public class StatusBar extends SystemUI implements ActivityStarter, LifecycleOwner {
public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
makeStatusBarView(result);
...代码省略...
mStatusBarWindowController.attach();
}
2、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);
...代码省略...
}
}
3、attach首先调用getBarLayoutParams方法获取状态栏类型窗口所需要的布局参数,下面是获取状态栏类型窗口所需要的布局参数的相关代码
private WindowManager.LayoutParams getBarLayoutParams(int rotation) {
WindowManager.LayoutParams lp = getBarLayoutParamsForRotation(rotation);
lp.paramsForRotation = new WindowManager.LayoutParams[4];
for (int rot = Surface.ROTATION_0; rot <= Surface.ROTATION_270; rot++) {
lp.paramsForRotation[rot] = getBarLayoutParamsForRotation(rot);
}
return lp;
}
private WindowManager.LayoutParams getBarLayoutParamsForRotation(int rotation) {
int height = mBarHeight;
if (INSETS_LAYOUT_GENERALIZATION) {
switch (rotation) {
case ROTATION_UNDEFINED:
case Surface.ROTATION_0:
case Surface.ROTATION_180:
height = SystemBarUtils.getStatusBarHeightForRotation(
mContext, Surface.ROTATION_0);
break;
case Surface.ROTATION_90:
height = SystemBarUtils.getStatusBarHeightForRotation(
mContext, Surface.ROTATION_90);
break;
case Surface.ROTATION_270:
height = SystemBarUtils.getStatusBarHeightForRotation(
mContext, Surface.ROTATION_270);
break;
}
}
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,//填充设备整个宽度
height,//根据当前屏幕旋转角度所得到的状态栏高度
WindowManager.LayoutParams.TYPE_STATUS_BAR,//指定窗口类型为状态栏
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
| WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
PixelFormat.TRANSLUCENT);//窗口背景半透明
lp.privateFlags |= PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
lp.token = new Binder();
lp.gravity = Gravity.TOP;
lp.setFitInsetsTypes(0 /* types */);
lp.setTitle("StatusBar");
lp.packageName = mContext.getPackageName();
lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
return lp;
}
4、在成功获取状态栏类型窗口所需要的布局参数后,便会调用WindowManager的addView方法将状态栏视图窗口添加到Window中。
经过前面几步,我们初步分析完了状态栏视图的创建和添加流程,最后用一张图对前面的代码流程做一个回顾。

出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在
如何使用RSpec::Core::RakeTask初始化RSpecRake任务?require'rspec/core/rake_task'RSpec::Core::RakeTask.newdo|t|#whatdoIputinhere?endInitialize函数记录在http://rubydoc.info/github/rspec/rspec-core/RSpec/Core/RakeTask#initialize-instance_method没有很好的记录;它只是说:-(RakeTask)initialize(*args,&task_block)AnewinstanceofRake
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?
我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法
我正在尝试按0-9和a-z的顺序创建数字和字母列表。我有一组值value_array=['0','1','2','3','4','5','6','7','8','9','a','b','光盘','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','','u','v','w','x','y','z']和一个组合列表的数组,按顺序,这些数字可以产生x个字符,比方说三个list_array=[]和一个当前字母和数字组合的数组(在将它插入列表数组之前我会把它变成一个字符串,]current_combo['0','0','0']
电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。 准备工作: 1、U盘一个(尽量使用8G以上的U盘)。 2、一台正常联网可使用的电脑。 3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。 4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。 U盘启动盘制作步骤: 注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt