当前位置: 首页 > news >正文

Android14 QS编辑页面面板的加载解析

/frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java

点击编辑按钮

mEditButton.setOnClickListener(view -> {if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {return;}mActivityStarter.postQSRunnableDismissingKeyguard(() -> mQsPanelController.showEdit(view));});

/frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java

QsCustomizerController开始显示

    /** Start customizing the Quick Settings. */public void showEdit(View view) {view.post(() -> {if (!mQsCustomizerController.isCustomizing()) {int[] loc = view.getLocationOnScreen();int x = loc[0] + view.getWidth() / 2;int y = loc[1] + view.getHeight() / 2;mQsCustomizerController.show(x, y, false);}});}

/frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java

视图开始显示,mView是指QSCustomizer这个视图

    @Injectprotected QSCustomizerController(QSCustomizer view, TileQueryHelper tileQueryHelper,QSHost qsHost, TileAdapter tileAdapter, ScreenLifecycle screenLifecycle,KeyguardStateController keyguardStateController, LightBarController lightBarController,ConfigurationController configurationController, UiEventLogger uiEventLogger) {super(view);mTileQueryHelper = tileQueryHelper;mQsHost = qsHost;mTileAdapter = tileAdapter;mScreenLifecycle = screenLifecycle;mKeyguardStateController = keyguardStateController;mLightBarController = lightBarController;mConfigurationController = configurationController;mUiEventLogger = uiEventLogger;mToolbar = mView.findViewById(com.android.internal.R.id.action_bar);}@Overrideprotected void onViewAttached() {mView.updateNavBackDrop(getResources().getConfiguration(), mLightBarController);mConfigurationController.addCallback(mConfigurationListener);//把mTileAdapter这个注册到mTileQueryHelper中,好方便加载完数据进行回调刷新viewmTileQueryHelper.setListener(mTileAdapter);......}public void show(int x, int y, boolean immediate) {if (!mView.isShown()) {setTileSpecs();if (immediate) {mView.showImmediately();} else {mView.show(x, y, mTileAdapter);mUiEventLogger.log(QSEditEvent.QS_EDIT_OPEN);}mTileQueryHelper.queryTiles(mQsHost);mKeyguardStateController.addCallback(mKeyguardCallback);mView.updateNavColors(mLightBarController);}}

/frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java

开始加载数据

    public void queryTiles(QSHost host) {mTiles.clear();mSpecs.clear();mFinished = false;// Enqueue jobs to fetch every system tile and then ever package tile.addCurrentAndStockTiles(host);}

/frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java

主要是R.string.quick_settings_tiles_stock,加载编辑面板中的Stock数据

private void addCurrentAndStockTiles(QSHost host) {String stock = mContext.getString(R.string.quick_settings_tiles_stock);String current = Settings.Secure.getString(mContext.getContentResolver(),Settings.Secure.QS_TILES);final ArrayList<String> possibleTiles = new ArrayList<>();if (current != null) {// The setting QS_TILES is not populated immediately upon Factory ResetpossibleTiles.addAll(Arrays.asList(current.split(",")));} else {current = "";}String[] stockSplit =  stock.split(",");for (String spec : stockSplit) {if (!current.contains(spec)) {possibleTiles.add(spec);}}if (Build.IS_DEBUGGABLE && !current.contains(GarbageMonitor.MemoryTile.TILE_SPEC)) {possibleTiles.add(GarbageMonitor.MemoryTile.TILE_SPEC);}final ArrayList<QSTile> tilesToAdd = new ArrayList<>();possibleTiles.remove("cell");possibleTiles.remove("wifi");for (String spec : possibleTiles) {// Only add current and stock tiles that can be created from QSFactoryImpl.// Do not include CustomTile. Those will be created by `addPackageTiles`.if (spec.startsWith(CustomTile.PREFIX)) continue;final QSTile tile = host.createTile(spec);if (tile == null) {continue;} else if (!tile.isAvailable()) {tile.setTileSpec(spec);tile.destroy();continue;}tile.setTileSpec(spec);tilesToAdd.add(tile);}new TileCollector(tilesToAdd, host).startListening();}

/frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java

实现监听QSTile的状态变化(观察者模式)

这里主要看这个地方:pair.mTile.refreshState()

  实现了QSTile.Callback回调private class TileCollector implements QSTile.Callback {private final List<TilePair> mQSTileList = new ArrayList<>();private final QSHost mQSHost;TileCollector(List<QSTile> tilesToAdd, QSHost host) {for (QSTile tile: tilesToAdd) {//包装一下TilePair pair = new TilePair(tile);mQSTileList.add(pair);}mQSHost = host;if (tilesToAdd.isEmpty()) {mBgExecutor.execute(this::finished);}}private void finished() {notifyTilesChanged(false);addPackageTiles(mQSHost);}//注册每个Tile的Callback回调和Listening回调,使得TileCollector作为监听者加入观察每个Tile的改变private void startListening() {for (TilePair pair: mQSTileList) {pair.mTile.addCallback(this);pair.mTile.setListening(this, true);// Make sure that at least one refresh state happenspair.mTile.refreshState();}}// This is called in the Bg thread@Overridepublic void onStateChanged(State s) {boolean allReady = true;for (TilePair pair: mQSTileList) {if (!pair.mReady && pair.mTile.isTileReady()) {pair.mTile.removeCallback(this);pair.mTile.setListening(this, false);pair.mReady = true;} else if (!pair.mReady) {allReady = false;}}if (allReady) {for (TilePair pair : mQSTileList) {QSTile tile = pair.mTile;final QSTile.State state = tile.getState().copy();// Ignore the current state and get the generic label instead.state.label = tile.getTileLabel();tile.destroy();addTile(tile.getTileSpec(), null, state, true);}finished();}}}

/frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java

每个Tile进行刷新自己的状态

	//第二步:进行状态刷新回调@Overridepublic void handleMessage(Message msg) {String name = null;try {......if (msg.what == REFRESH_STATE) {name = "handleRefreshState";handleRefreshState(msg.obj);}......}//第一步:发送Handler更新信息protected final void refreshState(@Nullable Object arg) {mHandler.obtainMessage(H.REFRESH_STATE, arg).sendToTarget();}//第三步:处理刷新逻辑protected final void handleRefreshState(@Nullable Object arg) {handleUpdateState(mTmpState, arg);boolean changed = mTmpState.copyTo(mState);if (mReadyState == READY_STATE_READYING) {mReadyState = READY_STATE_READY;changed = true;}if (changed) {mQSLogger.logTileUpdated(mTileSpec, mState);handleStateChanged();}mHandler.removeMessages(H.STALE);mHandler.sendEmptyMessageDelayed(H.STALE, getStaleTimeout());setListening(mStaleListener, false);}//第四步:这里触发状态改变回调private void handleStateChanged() {if (mCallbacks.size() != 0) {for (int i = 0; i < mCallbacks.size(); i++) {mCallbacks.get(i).onStateChanged(mState);}}}

/frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java

这里进行触发onStateChanged,遍历所有 tiles 都已就绪,如果已就绪,就添加到集合中进行存储,然后这时候就开始加载第三方的Tiles

// This is called in the Bg thread
@Override
public void onStateChanged(State s) {boolean allReady = true;  // 标记是否所有 tiles 都已就绪for (TilePair pair : mQSTileList) {  // 遍历所有待收集的 TilePair(包含 QSTile 和就绪状态)if (!pair.mReady && pair.mTile.isTileReady()) {  // 如果 tile 未标记就绪,且实际已就绪pair.mTile.removeCallback(this);  // 移除当前回调(避免重复监听)pair.mTile.setListening(this, false);  // 停止监听该 tile 的状态变化pair.mReady = true;  // 标记该 tile 为已就绪} else if (!pair.mReady) {  // 如果 tile 未就绪allReady = false;  // 则所有 tiles 未全部就绪}}if (allReady) {  // 当所有 tiles 都就绪后for (TilePair pair : mQSTileList) {  // 遍历所有就绪的 tilesQSTile tile = pair.mTile;final QSTile.State state = tile.getState().copy();  // 复制 tile 的当前状态(如图标、标签等)// Ignore the current state and get the generic label instead.state.label = tile.getTileLabel();  // 覆盖状态中的标签为 tile 的通用标签(忽略动态状态标签)tile.destroy();  // 销毁 tile 实例(释放资源,避免内存泄漏)addTile(tile.getTileSpec(), null, state, true);  // 将 tile 信息添加到全局列表(标记为系统 tile)}finished();  // 触发完成逻辑(通知监听器并继续处理第三方应用 tiles)}
}

/frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java

addPackageTiles 这里是添加第三方的Tiles

        private void finished() {notifyTilesChanged(false); //这里还未将数据绑定到视图中addPackageTiles(mQSHost);}
    private void addPackageTiles(final QSHost host) {mBgExecutor.execute(() -> {Collection<QSTile> params = host.getTiles();PackageManager pm = mContext.getPackageManager();// 查询所有声明了 TileService.ACTION_QS_TILE 的服务(即第三方 QS tile 服务)List<ResolveInfo> services = pm.queryIntentServicesAsUser(new Intent(TileService.ACTION_QS_TILE), 0, mUserTracker.getUserId());String stockTiles = mContext.getString(R.string.quick_settings_tiles_stock);for (ResolveInfo info : services) {String packageName = info.serviceInfo.packageName;ComponentName componentName = new ComponentName(packageName, info.serviceInfo.name);// Don't include apps that are a part of the default tile set.// 跳过系统默认 tile(已在 stockTiles 中的 tile 不重复添加)if (stockTiles.contains(componentName.flattenToString())) {continue;}final CharSequence appLabel = info.serviceInfo.applicationInfo.loadLabel(pm);String spec = CustomTile.toSpec(componentName);State state = getState(params, spec);if (state != null) {addTile(spec, appLabel, state, false);continue;}if (info.serviceInfo.icon == 0 && info.serviceInfo.applicationInfo.icon == 0) {continue;}Drawable icon = info.serviceInfo.loadIcon(pm);if (!permission.BIND_QUICK_SETTINGS_TILE.equals(info.serviceInfo.permission)) {continue;}if (icon == null) {continue;}icon.mutate();icon.setTint(mContext.getColor(android.R.color.white));CharSequence label = info.serviceInfo.loadLabel(pm);createStateAndAddTile(spec, icon, label != null ? label.toString() : "null",appLabel);}notifyTilesChanged(true);  // 通知监听器:第三方 tile 加载完成,可更新 UI});}

/frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java

这里开始将数据绑定到视图中,这个mListener是指mTileAdapter

    private void notifyTilesChanged(final boolean finished) {final ArrayList<TileInfo> tilesToReturn = new ArrayList<>(mTiles);mMainExecutor.execute(() -> {if (mListener != null) {mListener.onTilesChanged(tilesToReturn);}mFinished = finished;});}

/frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java

数据绑定进视图进行显示

 @Overridepublic void onTilesChanged(List<TileInfo> tiles) {mAllTiles = tiles;recalcSpecs();}private void recalcSpecs() {if (mCurrentSpecs == null || mAllTiles == null) {return;}mOtherTiles = new ArrayList<TileInfo>(mAllTiles);mTiles.clear();mTiles.add(null);for (int i = 0; i < mCurrentSpecs.size(); i++) {final TileInfo tile = getAndRemoveOther(mCurrentSpecs.get(i));if (tile != null) {mTiles.add(tile);}}mTiles.add(null);for (int i = 0; i < mOtherTiles.size(); i++) {final TileInfo tile = mOtherTiles.get(i);if (tile.isSystem) {mOtherTiles.remove(i--);mTiles.add(tile);}}mTileDividerIndex = mTiles.size();mTiles.add(null);mTiles.addAll(mOtherTiles);updateDividerLocations();notifyDataSetChanged();}
http://www.lryc.cn/news/617892.html

相关文章:

  • Android中Activity销毁底层原理
  • GSON 框架下百度天气 JSON 数据转 JavaBean 的实战攻略
  • Mysql——Sql的执行过程
  • 从 0 到 1:用 MyCat 打造可水平扩展的 MySQL 分库分表架构
  • Linux-常用命令
  • 深入解析 resolv.conf 文件:DNS 配置的核心
  • 驱动_ConfigFS多级目录操作
  • 光功率dBm为何是负数?一文详解
  • Google OAuth 配置步骤指南,实现Google Drive文件同步功能。
  • UVM验证—UVM 简述
  • 快速了解TF-IDF算法
  • 逐际动力开源运控 tron1-rl-isaacgym 解读与改进
  • 自由学习记录(81)
  • 5B 参数,消费级显卡可部署:Wan2.2-TI2V-5B 本地部署教程,9分钟跑出电影级大片!
  • 【运维进阶】WEB 服务器
  • GB17761-2024标准与电动自行车防火安全的技术革新
  • Redis 数据结构及特点
  • 【工作笔记】Wrappers.lambdaQuery()用法
  • ROS2学习(1)—基础概念及环境搭建
  • JavaEE 初阶第十七期:文件 IO 的 “管道艺术”(下)
  • vscode新建esp32工程,没有sample_project怎么办?
  • 计算机网络:ovn数据通信都是用了哪些协议?
  • 应用层模拟面试题
  • C语言(06)——二、八、十、十六进制的相互转换
  • Effective C++ 条款35:考虑 virtual函数以外的其他选择
  • 【已解决】报错:WARNING: pip is configured with locations that require TLS/SSL
  • HarmonyOS 开发入门 第一章
  • 一文读懂 C# 中的 Lazy<T>
  • Python 在自动化办公汇总和脚本示例
  • 本地文件夹与 GitHub 远程仓库绑定并进行日常操作的完整命令流程