Android14的QS面板的加載解析

/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java

QS 面板的創建

  1. getNotificationShadeWindowView():整個systemui的最頂級的視圖容器(super_notification_shade.xml)
  2. R.id.qs_frame : 是整個QS 面板的容器視圖
  3. mQSPanelController:獲取其內部的 QSPanelController(QS 面板的控制器,負責管理快捷開關的顯示、點擊事件等)
// Set up the quick settings tile paneprotected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {......final View container = getNotificationShadeWindowView().findViewById(R.id.qs_frame);if (container != null) {//FragmentHostManager:是 SystemUI 中用于管理 Fragment 與宿主視圖(這里即 container)關聯的工具類,負責 Fragment 的添加、移除、生命周期綁定等。FragmentHostManager fragmentHostManager =mFragmentService.getFragmentHostManager(container);ExtensionFragmentListener.attachExtensonToFragment(mFragmentService,container,QS.TAG,R.id.qs_frame,mExtensionController.newExtension(QS.class).withPlugin(QS.class).withDefault(this::createDefaultQSFragment).build());mBrightnessMirrorController = new BrightnessMirrorController(getNotificationShadeWindowView(),mShadeSurface,mNotificationShadeDepthControllerLazy.get(),mBrightnessSliderFactory,(visible) -> {mBrightnessMirrorVisible = visible;updateScrimController();});//給 fragmentHostManager 添加一個標簽監聽器,監聽 QS.TAG 對應的 Fragment(即 QS 面板的 Fragment)的生命周期變化(如 Fragment 被創建或綁定到容器時)fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> {QS qs = (QS) f;if (qs instanceof QSFragment) {mQSPanelController = ((QSFragment) qs).getQSPanelController();((QSFragment) qs).setBrightnessMirrorController(mBrightnessMirrorController);}});}
}

/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java

這里開始看創建面板QSFragment

    protected QS createDefaultQSFragment() {return mFragmentService.getFragmentHostManager(getNotificationShadeWindowView()).create(QSFragment.class);}

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

QSFragment 初始化

!!!這里的 qsFragmentComponent.getQSPanelController是重點,返回QSPanelController對象

    @Overridepublic void onViewCreated(View view, @Nullable Bundle savedInstanceState) {QSFragmentComponent qsFragmentComponent = mQsComponentFactory.create(this);mQSPanelController = qsFragmentComponent.getQSPanelController();mQuickQSPanelController = qsFragmentComponent.getQuickQSPanelController();mQSPanelController.init();mQuickQSPanelController.init();

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

QSPanelController初始化

!!!這里開始QSHost開始被注入創建,QSHost主要是數據源!!!

 @InjectQSPanelController(QSPanel view, TunerService tunerService,QSHost qsHost, QSCustomizerController qsCustomizerController,@Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer,@Named(QS_PANEL) MediaHost mediaHost,QSTileRevealController.Factory qsTileRevealControllerFactory,DumpManager dumpManager, MetricsLogger metricsLogger, UiEventLogger uiEventLogger,QSLogger qsLogger, BrightnessController.Factory brightnessControllerFactory,BrightnessSliderController.Factory brightnessSliderFactory,FalsingManager falsingManager,StatusBarKeyguardViewManager statusBarKeyguardViewManager) {super(view, qsHost, qsCustomizerController, usingMediaPlayer, mediaHost,metricsLogger, uiEventLogger, qsLogger, dumpManager);

QSHost提供實現類是QSHostAdapter

/frameworks/base/packages/SystemUI/src/com/android/systemui/qs/dagger/QSHostModule.kt

@Module
interface QSHostModule {//@Binds: 表明QSHostAdapter是QSHost的具體實現類,當其他類通過 Dagger 注入 QSHost 時(比如在構造函數中聲明 @Inject constructor(private val qsHost: QSHost)),Dagger 會自動創建 QSHostAdapter 的實例@Binds fun provideQsHost(controllerImpl: QSHostAdapter): QSHost
}

/frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSHostAdapter.kt

QSHostAdapter其實只是一個包裝類,具體實現是QSTileHost,記住這個地方

QSTileHost從此刻開始被注入創建

constructor(private val qsTileHost: QSTileHost,private val interactor: CurrentTilesInteractor,private val context: Context,private val tileServiceRequestControllerBuilder: TileServiceRequestController.Builder,@Application private val scope: CoroutineScope,private val featureFlags: FeatureFlags,dumpManager: DumpManager,
) : QSHost {

QSTileHost開始初始化

主要看這個tunerService.addTunable(this, TILES_SETTING);

    @Injectpublic QSTileHost(Context context,QSFactory defaultFactory,@Main Executor mainExecutor,PluginManager pluginManager,TunerService tunerService,Provider<AutoTileManager> autoTiles,ShadeController shadeController,QSLogger qsLogger,UserTracker userTracker,SecureSettings secureSettings,CustomTileStatePersister customTileStatePersister,TileLifecycleManager.Factory tileLifecycleManagerFactory,UserFileManager userFileManager,FeatureFlags featureFlags) {mainExecutor.execute(() -> {// This is technically a hack to avoid circular dependency of// QSTileHost -> XXXTile -> QSTileHost. Posting ensures creation// finishes before creating any tiles.//這個在	QSHost 中定義的String TILES_SETTING = Settings.Secure.QS_TILES;tunerService.addTunable(this, TILES_SETTING);// AutoTileManager can modify mTiles so make sure mTiles has already been initialized.if (!mFeatureFlags.isEnabled(Flags.QS_PIPELINE_AUTO_ADD)) {mAutoTiles = autoTiles.get();}});}

其實最后調用了QSTileHost的onTuningChanged方法

這里進行數據獲取!!!

private final LinkedHashMap<String, QSTile> mTiles = new LinkedHashMap<>();@MainThread@Overridepublic void onTuningChanged(String key, String newValue) {if (!TILES_SETTING.equals(key)) {return;}int currentUser = mUserTracker.getUserId();if (currentUser != mCurrentUser) {mUserContext = mUserTracker.getUserContext();if (mAutoTiles != null) {mAutoTiles.changeUser(UserHandle.of(currentUser));}}// Do not process tiles if the flag is enabled.if (mFeatureFlags.isEnabled(Flags.QS_PIPELINE_NEW_HOST)) {return;}if (newValue == null && UserManager.isDeviceInDemoMode(mContext)) {newValue = mContext.getResources().getString(R.string.quick_settings_tiles_retail_mode);}final List<String> tileSpecs = loadTileSpecs(mContext, newValue);if (tileSpecs.equals(mTileSpecs) && currentUser == mCurrentUser) return;Log.d(TAG, "Recreating tiles: " + tileSpecs);mTiles.entrySet().stream().filter(tile -> !tileSpecs.contains(tile.getKey())).forEach(tile -> {Log.d(TAG, "Destroying tile: " + tile.getKey());mQSLogger.logTileDestroyed(tile.getKey(), "Tile removed");tile.getValue().destroy();});final LinkedHashMap<String, QSTile> newTiles = new LinkedHashMap<>();for (String tileSpec : tileSpecs) {QSTile tile = mTiles.get(tileSpec);if (tile != null && (!(tile instanceof CustomTile)|| ((CustomTile) tile).getUser() == currentUser)) {if (tile.isAvailable()) {Log.d(TAG, "Adding " + tile);tile.removeCallbacks();if (!(tile instanceof CustomTile) && mCurrentUser != currentUser) {tile.userSwitch(currentUser);}newTiles.put(tileSpec, tile);mQSLogger.logTileAdded(tileSpec);} else {tile.destroy();Log.d(TAG, "Destroying not available tile: " + tileSpec);mQSLogger.logTileDestroyed(tileSpec, "Tile not available");}} else {// This means that the tile is a CustomTile AND the user is different, so let's// destroy itif (tile != null) {tile.destroy();Log.d(TAG, "Destroying tile for wrong user: " + tileSpec);mQSLogger.logTileDestroyed(tileSpec, "Tile for wrong user");}Log.d(TAG, "Creating tile: " + tileSpec);try {tile = createTile(tileSpec);if (tile != null) {tile.setTileSpec(tileSpec);if (tile.isAvailable()) {newTiles.put(tileSpec, tile);mQSLogger.logTileAdded(tileSpec);} else {tile.destroy();Log.d(TAG, "Destroying not available tile: " + tileSpec);mQSLogger.logTileDestroyed(tileSpec, "Tile not available");}} else {Log.d(TAG, "No factory for a spec: " + tileSpec);}} catch (Throwable t) {Log.w(TAG, "Error creating tile for spec: " + tileSpec, t);}}}........}

看這個loadTileSpecs

quick_settings_tiles:config.xml中的值是default

 protected static List<String> loadTileSpecs(Context context, String tileList) {final Resources res = context.getResources();if (TextUtils.isEmpty(tileList)) {tileList = res.getString(R.string.quick_settings_tiles);Log.d(TAG, "Loaded tile specs from default config: " + tileList);} else {Log.d(TAG, "Loaded tile specs from setting: " + tileList);}final ArrayList<String> tiles = new ArrayList<String>();boolean addedDefault = false;Set<String> addedSpecs = new ArraySet<>();for (String tile : tileList.split(",")) {tile = tile.trim();if (tile.isEmpty()) continue;if (tile.equals("default")) {if (!addedDefault) {List<String> defaultSpecs = QSHost.getDefaultSpecs(context.getResources());for (String spec : defaultSpecs) {if (!addedSpecs.contains(spec)) {tiles.add(spec);addedSpecs.add(spec);}}addedDefault = true;}} else {if (!addedSpecs.contains(tile)) {tiles.add(tile);addedSpecs.add(tile);}}}if (!tiles.contains("internet")) {if (tiles.contains("wifi")) {// Replace the WiFi with Internet, and remove the Celltiles.set(tiles.indexOf("wifi"), "internet");tiles.remove("cell");} else if (tiles.contains("cell")) {// Replace the Cell with Internettiles.set(tiles.indexOf("cell"), "internet");}} else {tiles.remove("wifi");tiles.remove("cell");}return tiles;}

QSHost

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

加載quick_settings_tiles_default是config下的配置文件,默認顯示下拉狀態欄的tiles

    /*** Returns the default QS tiles for the context.* @param res the resources to use to determine the default tiles* @return a list of specs of the default tiles*/static List<String> getDefaultSpecs(Resources res) {final ArrayList<String> tiles = new ArrayList();final String defaultTileList = res.getString(R.string.quick_settings_tiles_default);tiles.addAll(Arrays.asList(defaultTileList.split(",")));if (Build.IS_DEBUGGABLE&& GarbageMonitor.ADD_MEMORY_TILE_TO_DEFAULT_ON_DEBUGGABLE_BUILDS) {tiles.add(GarbageMonitor.MemoryTile.TILE_SPEC);}return tiles;}

這時候的數據已經加載完,接下來看創建Tile實例

    private final ArrayList<QSFactory> mQsFactories = new ArrayList<>();public QSTile createTile(String tileSpec) {for (int i = 0; i < mQsFactories.size(); i++) {QSTile t = mQsFactories.get(i).createTile(tileSpec);if (t != null) {return t;}}return null;}

!!!其實是QSFactoryImpl 去createTile!!!

經過bind自動注入到mTileMap中了,
這時候用quick_settings_tiles_default去跟mTileMap比較是否存在,存在就返回對應注入好的Tile實例對象

/** Inject FontScalingTile into tileMap in QSModule */
@Binds
@IntoMap
@StringKey(FontScalingTile.TILE_SPEC)
fun bindFontScalingTile(fontScalingTile: FontScalingTile): QSTileImpl<*>

@SysUISingleton
public class QSFactoryImpl implements QSFactory {private static final String TAG = "QSFactory";protected final Map<String, Provider<QSTileImpl<?>>> mTileMap;private final Lazy<QSHost> mQsHostLazy;private final Provider<CustomTile.Builder> mCustomTileBuilderProvider;@Injectpublic QSFactoryImpl(Lazy<QSHost> qsHostLazy,Provider<CustomTile.Builder> customTileBuilderProvider,Map<String, Provider<QSTileImpl<?>>> tileMap) {mQsHostLazy = qsHostLazy;mCustomTileBuilderProvider = customTileBuilderProvider;mTileMap = tileMap;}/** Creates a tile with a type based on {@code tileSpec} */@Nullablepublic final QSTile createTile(String tileSpec) {QSTileImpl tile = createTileInternal(tileSpec);if (tile != null) {tile.initialize();tile.postStale(); // Tile was just created, must be stale.}return tile;}@Nullableprotected QSTileImpl createTileInternal(String tileSpec) {// Stock tiles.if (mTileMap.containsKey(tileSpec)// We should not return a Garbage Monitory Tile if the build is not Debuggable&& (!tileSpec.equals(GarbageMonitor.MemoryTile.TILE_SPEC) || Build.IS_DEBUGGABLE)) {return mTileMap.get(tileSpec).get();}// Custom tilesif (tileSpec.startsWith(CustomTile.PREFIX)) {return CustomTile.create(mCustomTileBuilderProvider.get(), tileSpec, mQsHostLazy.get().getUserContext());}// Broken tiles.Log.w(TAG, "No stock tile spec: " + tileSpec);return null;}@Overridepublic QSTileView createTileView(Context context, QSTile tile, boolean collapsedView) {QSIconView icon = tile.createTileView(context);return new QSTileViewImpl(context, icon, collapsedView);}

最重要的這一步,獲取到全部的數據緩存在mTiles中保存!!!

用戶視圖加載數據用!!!
public Collection getTiles() {return mTiles.values();}

  @MainThread@Overridepublic void onTuningChanged(String key, String newValue) {......mCurrentUser = currentUser;List<String> currentSpecs = new ArrayList<>(mTileSpecs);mTileSpecs.clear();mTileSpecs.addAll(newTiles.keySet()); // Only add the valid (available) tiles.mTiles.clear();mTiles.putAll(newTiles);if (newTiles.isEmpty() && !tileSpecs.isEmpty()) {// If we didn't manage to create any tiles, set it to empty (default)Log.d(TAG, "No valid tiles on tuning changed. Setting to default.");changeTilesByUser(currentSpecs, loadTileSpecs(mContext, ""));} else {String resolvedTiles = TextUtils.join(",", mTileSpecs);if (!resolvedTiles.equals(newValue)) {// If the resolved tiles (those we actually ended up with) are different than// the ones that are in the setting, update the Setting.// 用TILES_SETTING進行緩存下拉狀態欄的數據saveTilesToSettings(mTileSpecs);}mTilesListDirty = false;for (int i = 0; i < mCallbacks.size(); i++) {mCallbacks.get(i).onTilesChanged();}}
}

接下來再看QSFragment 初始化,這時候數據類都已經加載好了,要開始把數據加載進視圖里面去了

mQSPanelController.init開始初始化,
/frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {QSFragmentComponent qsFragmentComponent = mQsComponentFactory.create(this);//start 這里調用完后數據已經加載完畢mQSPanelController = qsFragmentComponent.getQSPanelController();//endmQuickQSPanelController = qsFragmentComponent.getQuickQSPanelController();//數據加載進視圖mQSPanelController.init();mQuickQSPanelController.init();

這個init()這里調用的其實是他的基類的init

/frameworks/base/packages/SystemUI/src/com/android/systemui/util/ViewController.java
這里其實是調用子類onViewAttached

 */
public abstract class ViewController<T extends View> {protected final T mView;private boolean mInited;private OnAttachStateChangeListener mOnAttachStateListener = new OnAttachStateChangeListener() {@Overridepublic void onViewAttachedToWindow(View v) {ViewController.this.onViewAttached();}@Overridepublic void onViewDetachedFromWindow(View v) {ViewController.this.onViewDetached();}};protected ViewController(T view) {mView = view;}/*** Call immediately after constructing Controller in order to handle view lifecycle events.** Generally speaking, you don't want to override this method. Instead, override* {@link #onInit()} as a way to have an run-once idempotent method that you can use for* setup of your ViewController.*/public void init() {if (mInited) {return;}onInit();mInited = true;if (isAttachedToWindow()) {mOnAttachStateListener.onViewAttachedToWindow(mView);}addOnAttachStateChangeListener(mOnAttachStateListener);}

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

這里是最重要的

這里獲取QSTileHost.getTiles()的數據進行數據與視圖綁定了
mView這個View是QSPanel,是QSPanelController這個類通過super傳遞給QSPanelControllerBase的
QSPanelController(QSPanel view, TunerService tunerService,....)
super(view,......)

    @Overrideprotected void onViewAttached() {mQsTileRevealController = createTileRevealController();if (mQsTileRevealController != null) {mQsTileRevealController.setExpansion(mRevealExpansion);}mMediaHost.addVisibilityChangeListener(mMediaHostVisibilityListener);mView.addOnConfigurationChangedListener(mOnConfigurationChangedListener);mHost.addCallback(mQSHostCallback);setTiles();mLastOrientation = getResources().getConfiguration().orientation;mQSLogger.logOnViewAttached(mLastOrientation, mView.getDumpableTag());switchTileLayout(true);mDumpManager.registerDumpable(mView.getDumpableTag(), this);}/** */public void setTiles() {setTiles(mHost.getTiles(), false);}/** */public void setTiles(Collection<QSTile> tiles, boolean collapsedView) {// TODO(b/168904199): move this logic into QSPanelController.if (!collapsedView && mQsTileRevealController != null) {mQsTileRevealController.updateRevealedTiles(tiles);}for (QSPanelControllerBase.TileRecord record : mRecords) {mView.removeTile(record);record.tile.removeCallback(record.callback);}mRecords.clear();mCachedSpecs = "";// 開始一個個添加進視圖中for (QSTile tile : tiles) {addTile(tile, collapsedView);}}private void addTile(final QSTile tile, boolean collapsedView) {final TileRecord r =new TileRecord(tile, mHost.createTileView(getContext(), tile, collapsedView));// TODO(b/250618218): Remove the QSLogger in QSTileViewImpl once we know the root cause of// b/250618218.try {QSTileViewImpl qsTileView = (QSTileViewImpl) (r.tileView);if (qsTileView != null) {qsTileView.setQsLogger(mQSLogger);}} catch (ClassCastException e) {Log.e(TAG, "Failed to cast QSTileView to QSTileViewImpl", e);}mView.addTile(r);mRecords.add(r);mCachedSpecs = getTilesSpecs();}

QSPanel

mTileLayout 中添加addTile

final void addTile(QSPanelControllerBase.TileRecord tileRecord) {//建立回調事件final QSTile.Callback callback = new QSTile.Callback() {@Overridepublic void onStateChanged(QSTile.State state) {drawTile(tileRecord, state);}};//向對應的QSTile注冊回調,然后會執行到 drawTile(tileRecord, state);這個方法是刷新每一個QSTileStatetileRecord.tile.addCallback(callback);tileRecord.callback = callback;//其實是在QSTileViewImpl.kt初始化點擊事件tileRecord.tileView.init(tileRecord.tile);tileRecord.tile.refreshState();if (mTileLayout != null) {mTileLayout.addTile(tileRecord);}}

TileLayout

    public void addTile(TileRecord tile) {mRecords.add(tile);tile.tile.setListening(this, mListening);addTileView(tile);}protected void addTileView(TileRecord tile) {addView(tile.tileView); 添加子view并刷新}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/917916.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/917916.shtml
英文地址,請注明出處:http://en.pswp.cn/news/917916.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

解鎖webpack核心技能(二):配置文件和devtool配置指南

一、配置文件webpack 提供的 cli 支持很多的參數&#xff0c;例如 --mode 。在我們平時的開發過程中&#xff0c;我們要學習很多的功能&#xff0c;這些很多都是可以用參數來完成的。那么后邊就會導致參數越來越多&#xff0c;我們使用命令特別的不方便&#xff0c;所以我們會使…

Gitlab+Jenkins+K8S+Registry 建立 CI/CD 流水線

一、前言 DevOps是一種將開發&#xff08;Development&#xff09;和運維&#xff08;Operations&#xff09;相結合的軟件開發方法論。它通過自動化和持續交付的方式&#xff0c;將軟件開發、測試和部署等環節緊密集成&#xff0c;以提高效率和產品質量。在本篇博客中&#xf…

【Linux】特效爆滿的Vim的配置方法 and make/Makefile原理

一、軟件包管理器 1、Linux下安裝軟件的常見方式&#xff1a; 1&#xff09;源代碼安裝——不推薦。 2&#xff09;rpm包安裝——不推薦。 3&#xff09;包管理器安裝——推薦 2、安裝軟件命令 # Centos$ sudo yum install -y lrzsz# Ubuntu$ sudo apt install -y lrzsz 3、卸…

Spring Boot Actuator 監控功能的簡介及禁用

Spring Boot Actuator: Production-ready Features 1. 添加依賴 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency> </dependencie…

Matlab(1)

一、基本操作1. matlab四則運算規則&#xff1a;先乘除后加減&#xff0c;從左到右2、對數和指數的表示sin(pi^0.5)log(tan(1))exp&#xff08;sin&#xff08;10&#xff09;&#xff09;3、類型&#xff1a;matlab變量默認為double4、who&whos&#xff1a;命令行輸入who&…

Kotlin Android 開發腳手架封裝

Kotlin Android 開發腳手架封裝&#xff08;模塊化版本&#xff09; 我將按照模塊化設計原則&#xff0c;將腳手架拆分為多個文件&#xff0c;每個文件負責特定功能領域&#xff1a; 1. 核心初始化模塊 文件路徑: core/AppScaffold.kt object AppScaffold {lateinit var contex…

Flutter 報錯解析:No TabController for TabBar 的完整解決方案

目錄 Flutter 報錯解析&#xff1a;No TabController for TabBar 的完整解決方案 一、錯誤場景&#xff1a;當 TabBar 失去 "指揮官" 二、為什么 TabBar 必須依賴 Controller&#xff1f; 1. TabBar 與 TabController 的協作關系 2. 狀態管理的核心作用 3. 實戰…

【24】C++實戰篇——【 C++ 外部變量】 C++多個文件共用一個枚舉變量,外部變量 extern,枚舉外部變量 enum

文章目錄1 方法2 外部變量 應用2.1 普通外部全局變量2.2 枚舉外部全局變量 應用2.2.2 枚舉外部變量優化c多個文件中如何共用一個全局變量 c頭文件的使用和多個文件中如何共用一個全局變量 C共享枚舉類型給QML 1 方法 ①頭文件中 聲明外部全局變量&#xff1b; ②在頭文件對…

Linux SELinux 核心概念與管理

Linux SELinux 核心概念與管理一、SELinux 基本概念 SELinux 即安全增強型 Linux&#xff08;Security-Enhanced Linux&#xff09;&#xff0c;由美國國家安全局&#xff08;NSA&#xff09;開發&#xff0c;是一套基于強制訪問控制&#xff08;MAC&#xff09;的安全機制&…

Git 中**未暫存**和**未跟蹤**的區別:

文件狀態分類 Git 中的文件有以下幾種狀態&#xff1a; 工作區文件狀態&#xff1a; ├── 未跟蹤 (Untracked) ├── 已跟蹤 (Tracked)├── 未修改 (Unmodified) ├── 已修改未暫存 (Modified/Unstaged)└── 已暫存 (Staged)1. 未跟蹤 (Untracked) 定義&#xff1a;Gi…

前端1.0

目錄 一、 什么是前端 二、 HTML 1.0 概述 2.0 注釋 三、開發環境的搭建 1.0 插件 2.0 筆記 四、 常見標簽&#xff08;重點&#xff09; 四、案例展示&#xff08;圖片代碼&#xff09; 五、CSS引入 一、 什么是前端 web前端 用來直接給用戶呈現一個一個的網頁 …

Flutter鏡像替換

一、核心鏡像替換&#xff08;針對 Maven 倉庫&#xff09; Flutter 依賴的 Google Maven 倉庫&#xff08;https://maven.google.com 或 https://dl.google.com/dl/android/maven2&#xff09;可替換為國內鏡像&#xff0c;常見的有&#xff1a;阿里云鏡像&#xff08;推薦&am…

MATLAB實現的改進遺傳算法用于有約束優化問題

基于MATLAB實現的改進遺傳算法&#xff08;GA&#xff09;用于有約束優化問題的代碼&#xff0c;包括處理非線性約束。此代碼通過引入懲罰函數和修復機制&#xff0c;有效處理約束條件&#xff0c;提高算法的魯棒性和收斂速度。 1. 定義優化問題 % 定義目標函數 function f ob…

Qt子類化QWidget后,使用setStyleSheet設置樣式無效的解決方案

關鍵代碼&#xff1a; #include <QPainter> #include <QStyleOption>void paintEvent(QPaintEvent *e) {QStyleOption opt;opt.init(this);QPainter p(this);style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);QWidget::paintEvent(e); }定義…

【python中級】關于Flask服務在同一系統里如何只被運行一次

【python中級】關于Flask服務在同一系統里如何只被運行一次 1.背景 2.方案1 2.方案2 1.背景 python Flask實現的一個http服務,打包成應用程序exe后在windows10系統運行; 由于我會不斷的更新這個http服務,我希望運行這個http服務的時候之前的http服務被停掉; 即實現 Pytho…

git配置公鑰/密鑰

遇到 “gitgithub.com: Permission denied (publickey)” 錯誤通常意味著你嘗試通過 SSH 連接到 GitHub 時&#xff0c;SSH 密鑰沒有被正確設置或者 GitHub 無法識別你的公鑰。這里有幾個步驟可以幫助你解決這個問題&#xff1a; 檢查 SSH 密鑰 首先&#xff0c;確保你已經在本…

【機器學習】“回歸“算法模型的三個評估指標:MAE(衡量預測準確性)、MSE(放大大誤差)、R2(說明模型解釋能力)

文章目錄一、MAE、MSE、r概念說明二、MAE&#xff08;平均絕對誤差&#xff09;&#xff1a;用"房價預測"理解誤差測量三、MSE&#xff08;均方誤差&#xff09;&#xff1a;誤差的"放大鏡"1、概念說明2、 sklearn代碼實踐3、流程總結四、R&#xff1a;理解…

智慧城市SaaS平臺|市容環衛管理系統

【生活垃圾中轉設施監管】1) 設施信息管理a) 設施基本信息支持記錄中轉設施的名稱、位置、類型、容量、負責人等基本信息。b) 設施分布地圖支持通過GIS地圖展示中轉設施的分布情況&#xff0c;支持地圖查詢和導航。2) 垃圾收運監控a) 垃圾收運記錄支持記錄垃圾收運的時間、車輛…

JAVA-13常用類(2025.08.02學習記錄)

String類String類equals方法String類compareTo方法String類valueOf方法boolean參數內存分析_字符串拼接只會在內存中開辟一個對象內存分析_字符串new創建對象內存分析_變量和字符串拼接字節碼執行過程String類內存分析package com.cn;public class test01 {public static void …

QT----簡單的htttp服務器與客戶端

HTTP協議學習 協議的相關學習可以參考這篇 csdn學習連接 總體流程如下 HTTP服務器 監聽ip和端口,有連接時接收請求,發送回復 server.h #pragma once #include <QtWidgets/QMainWindow> #include "ui_httpServer.h" #include <QTcpServer> #include &l…