Android 12系統源碼_多屏幕(四)自由窗口模式

一、小窗模式

1.1 小窗功能的開啟方式

  • 開發者模式下開啟小窗功能
    在這里插入圖片描述
  • adb 手動開啟
adb shell settings put global enable_freeform_support  1
adb shell settings put global force_resizable_activities  1

1.2 源碼配置

  • copy file
# add for freedom
PRODUCT_COPY_FILES += \frameworks/native/data/etc/android.software.freeform_window_management.xml:$(TARGET_COPY_OUT_SYSTEM)/etc/permissions/android.software.freeform_window_management.xml
  • overlay
    <!-- add for freeform --><bool name="config_freeformWindowManagement">true</bool>

1.3 小窗的啟動方式

主要的啟動方式,一個是多任務里面,點擊應用圖標,選擇小窗模式,另一個是通過三方應用啟動,比如側邊欄,通知欄等待。

  • 三方應用通過ActivityOptions 啟動
    public void startFreeFormActivity(View view) {Intent intent = new Intent(this, FreeFormActivity.class);ActivityOptions options = ActivityOptions.makeBasic();options.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);startActivity(intent, options.toBundle());}
  • 多任務啟動
    通過長按應用圖標,選擇小窗模式,ActivityOptions 會設置 ActivityOptions#setLaunchWindowingMode 為 WINDOWING_MODE_FREEFORM,然后通過 ActivityManager#startActivity 啟動 Activity。

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java

public class ActivityTaskSupervisor implements RecentTasks.Callbacks {int startActivityFromRecents(int callingPid, int callingUid, int taskId,SafeActivityOptions options) {...代碼省略...        }
}

1.4 應用兼容

應用需要設置 android:resizeableActivity=“true”,應用安裝過程中會解析AndroidManifest.xml,并設置 PackageParser.ActivityInfo 的 privateFlags,在啟動應用的時候,會根據 privateFlags 的值來判斷是否支持小窗。

        if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity, true)) {ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;} else {ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;}} else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;}

1.5 基礎的窗口信息

在Android 系統中,窗口是應用程序界面的基本單元,用于承載和顯示應用的視圖內容。每個 Activity 都有一個主窗口,但也可以有其他窗口,如對話框、懸浮窗等。

在應用上層的一些組件的體現上,變化不是很大,但是 Framework 中的對于窗口的管理,迭代變化一直都比較大,可能之前有的類,新的架構下就被精簡了,所以主要掌握窗口的一些概念,這樣比較容易在新的架構之下找到對應的實現。

這里先回顧一下基礎的窗口和界面相關的概念:

  • Window(窗口): 窗口是應用程序界面的基本單元,用于承載和顯示應用的視圖內容。每個 Activity 都有一個主窗口,但也可以有其他窗口,如對話框、懸浮窗等。
  • WindowManagerService: 是 Android 系統中的窗口管理服務,負責管理窗口的創建、顯示、移動、調整大小、層級關系等。它是 Android 窗口系統的核心組件。
  • View(視圖): View 是 Android 中用戶界面的基本構建塊,用于在窗口中繪制和顯示內容。它是窗口中可見元素的基礎。
  • ViewGroup(視圖組): ViewGroup 是一種特殊的 View,它可以包含其他視圖(包括 View 和其他 ViewGroup)來形成復雜的用戶界面。
  • Surface(表面): Surface 是用于繪制圖形內容的區域,窗口和視圖內容都可以在 Surface 上繪制。每個窗口通常對應一個 Surface。
  • SurfaceFlinger: 是 Android 系統中的一個組件,負責管理和合成窗口中的 Surface,以及在屏幕上繪制這些 Surface。
  • LayoutParams(布局參數): LayoutParams 是窗口或視圖的布局參數,用于指定視圖在其父視圖中的位置、大小和外觀等。
  • Window Token(窗口令牌): Window Token 是一個用于標識窗口所屬于的應用程序或任務的對象。它在窗口的顯示和交互中起著重要作用。
  • Window Decor(窗口裝飾): Window Decor 是窗口的裝飾元素,如標題欄、狀態欄等,可以影響窗口的外觀和交互。
  • Dialog(對話框): 對話框是一種特殊的窗口,用于在當前活動之上顯示臨時的提示、選擇或輸入內容。
  • Activity(活動): 在 Android 應用程序中,每個 Activity 都與一個 PhoneWindow 相關聯。PhoneWindow 用于管理 Activity 的界面繪制和交互。
  • Window Callback(窗口回調): PhoneWindow 實現了 Window.Callback 接口,該接口用于處理窗口事件和交互。通過實現這個接口,您可以監聽和響應窗口的狀態變化、輸入事件等。
  • DecorView(裝飾視圖): PhoneWindow 中的內容通常由 DecorView 承載。DecorView 是一個特殊的 ViewGroup,用于包含應用程序的用戶界面內容和窗口裝飾元素,如標題欄、狀態欄等。
  • PhoneWindow(應用程序窗口): PhoneWindow 是 android.view.Window 類的實現之一,用于表示一個應用程序窗口。它提供了窗口的基本功能,如繪制、布局、裝飾、焦點管理等。

1.6 窗口類型

frameworks/base/core/java/android/app/WindowConfiguration.java

public class WindowConfiguration implements Parcelable, Comparable<WindowConfiguration> {public static final int WINDOWING_MODE_UNDEFINED = 0;public static final int WINDOWING_MODE_FULLSCREEN = 1;//全屏窗口模式public static final int WINDOWING_MODE_PINNED = 2;//固定窗口模式public static final int WINDOWING_MODE_SPLIT_SCREEN_PRIMARY = 3;public static final int WINDOWING_MODE_SPLIT_SCREEN_SECONDARY = 4;public static final int WINDOWING_MODE_FREEFORM = 5;//自由窗口模式public static final int WINDOWING_MODE_MULTI_WINDOW = 6;//多窗口模式/** @hide */@IntDef(prefix = { "WINDOWING_MODE_" }, value = {WINDOWING_MODE_UNDEFINED,WINDOWING_MODE_FULLSCREEN,WINDOWING_MODE_MULTI_WINDOW,WINDOWING_MODE_PINNED,WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,WINDOWING_MODE_FREEFORM,})public @interface WindowingMode {}
}

二、小窗的創建

小窗的創建時機有兩塊,一塊是在頁面創建的時候,也就是PhoneWindow創建的時候,會創建DecorView,DecorView 會判斷是否要創立一個 DecorCaptionView。 另外一塊當DecorView動態變化的時候,當有參數變量,經過onWindowSystemUiVisibilityChanged方法回調或者 onConfigurationChanged方法回調,系統會對DecorView 進行更新并判斷是否需要新建一個小窗DecorCaptionView的視圖。

2.1 頁面創建的時候創建小窗

>frameworks/base/core/java/android/app/Activity.java
public class Activity extends ContextThemeWrapperimplements LayoutInflater.Factory2,Window.Callback, KeyEvent.Callback,OnCreateContextMenuListener, ComponentCallbacks2,Window.OnWindowDismissedCallback,ContentCaptureManager.ContentCaptureClient {public void setContentView(View view) {//注釋1,調用PhoneWindow的setContentView方法getWindow().setContentView(view);initWindowDecorActionBar();}}>frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java  
public class PhoneWindow extends Window implements MenuBuilder.Callback {private DecorView mDecor;ViewGroup mContentParent;@Overridepublic void setContentView(View view, ViewGroup.LayoutParams params) {if (mContentParent == null) {//注釋2,調用installDecorinstallDecor();} ...代碼省略...}private void installDecor() {...代碼省略...//注釋3,創建窗口對應的DecorView視圖mDecor = generateDecor(-1);...代碼省略...//注釋4,調用generateLayout方法mContentParent = generateLayout(mDecor);            }protected ViewGroup generateLayout(DecorView decor) {...代碼省略...//注釋5,調用DecorView的onResourcesLoaded方法mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);  ...代碼省略...          }
}>frameworks/base/core/java/com/android/internal/policy/DecorView.java
public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {//加載應用需要的布局資源void onResourcesLoaded(LayoutInflater inflater, int layoutResource) {...代碼省略...//創建小窗視圖mDecorCaptionView = createDecorCaptionView(inflater);//應用需要加載的根布局final View root = inflater.inflate(layoutResource, null);if (mDecorCaptionView != null) {//注釋6,如果小窗視圖不為空,則將小窗的視圖添加到DecorView中if (mDecorCaptionView.getParent() == null) {addView(mDecorCaptionView,new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));}//然后將應用根布局添加到mDecorCaptionView中mDecorCaptionView.addView(root,new ViewGroup.MarginLayoutParams(MATCH_PARENT, MATCH_PARENT));} else {//注釋7,如果不是小窗,則將應用根布局添加到DecorView中addView(root, 0, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));}mContentRoot = (ViewGroup) root;initializeElevation();}private DecorCaptionView createDecorCaptionView(LayoutInflater inflater) {DecorCaptionView decorCaptionView = null;for (int i = getChildCount() - 1; i >= 0 && decorCaptionView == null; i--) {View view = getChildAt(i);if (view instanceof DecorCaptionView) {// The decor was most likely saved from a relaunch - so reuse it.decorCaptionView = (DecorCaptionView) view;removeViewAt(i);}}final WindowManager.LayoutParams attrs = mWindow.getAttributes();final boolean isApplication = attrs.type == TYPE_BASE_APPLICATION ||attrs.type == TYPE_APPLICATION || attrs.type == TYPE_DRAWN_APPLICATION;final WindowConfiguration winConfig = getResources().getConfiguration().windowConfiguration;// Only a non floating application window on one of the allowed workspaces can get a captionif (!mWindow.isFloating() && isApplication && winConfig.hasWindowDecorCaption()) {// Dependent on the brightness of the used title we either use the// dark or the light button frame.if (decorCaptionView == null) {//調用inflateDecorCaptionView方法decorCaptionView = inflateDecorCaptionView(inflater);}decorCaptionView.setPhoneWindow(mWindow, true /*showDecor*/);} else {decorCaptionView = null;}enableCaption(decorCaptionView != null);return decorCaptionView;}private DecorCaptionView inflateDecorCaptionView(LayoutInflater inflater) {final Context context = getContext();inflater = inflater.from(context);//注釋8,構建小窗對應的布局文件final DecorCaptionView view = (DecorCaptionView) inflater.inflate(R.layout.decor_caption,null);setDecorCaptionShade(view);return view;}
}

如上所示Activity的setContentView方法經過層層調用最終會觸發DecorView的onResourcesLoaded方法,如果是小窗模式,會走到注釋6處,將頁面需要的布局資源添加到DecorCaptionView中,然后將DecorCaptionView添加到DecorView中;如果是普通應用場景,會走到注釋7處,會將布局資源添加到DecorView中;最終WMS會將DecorView添加到屏幕上。另外在注釋8處可以看到小窗加載的是什么布局資源。

2.2 在DecorView的回調方法中創建小窗

public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {@Overridepublic void onWindowSystemUiVisibilityChanged(int visible) {updateColorViews(null /* insets */, true /* animate */);//調用updateDecorCaptionStatus方法更新小窗的狀態updateDecorCaptionStatus(getResources().getConfiguration());if (mStatusGuard != null && mStatusGuard.getVisibility() == VISIBLE) {updateStatusGuardColor();}}@Overrideprotected void onConfigurationChanged(Configuration newConfig) {super.onConfigurationChanged(newConfig);//調用updateDecorCaptionStatus方法更新小窗的狀態updateDecorCaptionStatus(newConfig);initializeElevation();}private void updateDecorCaptionStatus(Configuration config) {//如果定義窗口類型為小窗,且不是全屏模式, 則創建一個DecorCaptionView在DecorView內部。final boolean displayWindowDecor = config.windowConfiguration.hasWindowDecorCaption()&& !isFillingScreen(config);if (mDecorCaptionView == null && displayWindowDecor) {// Configuration now requires a caption.final LayoutInflater inflater = mWindow.getLayoutInflater();//注釋1,調用createDecorCaptionView方法創建小窗視圖mDecorCaptionView = createDecorCaptionView(inflater);if (mDecorCaptionView != null) {if (mDecorCaptionView.getParent() == null) {addView(mDecorCaptionView, 0,new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));}removeView(mContentRoot);mDecorCaptionView.addView(mContentRoot,new ViewGroup.MarginLayoutParams(MATCH_PARENT, MATCH_PARENT));}} else if (mDecorCaptionView != null) {//注釋2,如果已經創建了 DecorCaptionView, 則更新配置信息,比如窗口大小,窗口位置等。mDecorCaptionView.onConfigurationChanged(displayWindowDecor);// 是否顯示小窗的標題欄enableCaption(displayWindowDecor);}}
}

在DecorView的onWindowSystemUiVisibilityChanged回調方法和onConfigurationChanged回調方法中,都會進一步調用updateDecorCaptionStatus方法;然后如果判斷需要創建小窗且小窗還未被創建,則在注釋1處,會調用createDecorCaptionView方法創建小窗視圖;否則在注釋2處,調用DecorCaptionView的onConfigurationChanged方法通知小窗進行配置變化。

三、小窗的實現

2.2 小窗的標題欄

frameworks/base/core/java/com/android/internal/widget/DecorCaptionView.java

public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,GestureDetector.OnGestureListener {private View mCaption;  // 標題欄private View mContent; // 小窗View之下,應用的根Viewprivate View mMaximize; // 最大化按鈕private View mClose; // 關閉按鈕
}

2.3 觸摸事件

public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {//如果在應用的小窗View外部點擊的話,直接將事件攔截掉,這樣就不會觸發應用的點擊事件。@Overridepublic boolean onInterceptTouchEvent(MotionEvent event) {int action = event.getAction();//是否顯示小窗標題欄if (mHasCaption && isShowingCaption()) {//如果窗口可調整大小,并且事件是(開始)在小窗外部,則不要將 ACTION_DOWN 事件進行傳遞。窗口調整大小事件應由WindowManager處理。if (action == MotionEvent.ACTION_DOWN) {final int x = (int) event.getX();final int y = (int) event.getY();if (isOutOfInnerBounds(x, y)) {return true;}}}...代碼省略...return false;}
}

frameworks/base/core/java/com/android/internal/widget/DecorCaptionView.java

public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,GestureDetector.OnGestureListener {private View mClickTarget;@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {//如果用戶點擊最大化或者關閉按鈕,就攔截事件,這樣就不會觸發應用的點擊事件if (ev.getAction() == MotionEvent.ACTION_DOWN) {final int x = (int) ev.getX();final int y = (int) ev.getY();//Only offset y for containment tests because the actual views are already translated.//是否點擊到最大化按鈕的區域if (mMaximizeRect.contains(x, y - mRootScrollY)) {mClickTarget = mMaximize;}//是否點擊到關閉按鈕的區域if (mCloseRect.contains(x, y - mRootScrollY)) {mClickTarget = mClose;}}return mClickTarget != null;}}

在小窗的View中,應用就不能通過View的事件來直接處理,DecorCaptionView 需要通過計算View所在的矩形區域,然后計算點擊的區域是否處于該矩形區域范圍內判斷為點擊,就是一個點和面的問題,原生小窗上的問題就是這個觸控面太小,手指的點擊區域可能不容易觸發。 (在我開發的ChatDev游戲中,也有面和面碰撞的問題,玩家的位置和碰撞位置的計算)

2.4 小窗的邊界

目前國內的廠商的小窗設計,都是通過在DecorView里面模仿DecorCaptionView自定義一個View,用來作為小窗內部應用的容器。

  • 邊界圓角 一般會對這個小窗容器進行一個UI上的美化,主要的一個就是邊界的圓角輪廓繪制。

  • 導航欄重疊的問題

DisplayPolicy 作為系統里面控制顯示 dock欄、狀態欄、導航欄的樣式的主要類, 在每次繪制布局之后,都會走到如下applyPostLayoutPolicyLw 函數,進行顯示規則的條件,當判斷重疊之后,在導航欄更新透明度規則的時候,將其標記中不透明的純深色背景和淺色前景清空。

public class DisplayPolicy {public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,WindowState attached, WindowState imeTarget) {final boolean affectsSystemUi = win.canAffectSystemUiFlags();if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": affectsSystemUi=" + affectsSystemUi);applyKeyguardPolicy(win, imeTarget);// 檢查自由窗口是否與導航欄區域重疊。final boolean isOverlappingWithNavBar = isOverlappingWithNavBar(win);if (isOverlappingWithNavBar && !mIsFreeformWindowOverlappingWithNavBar&& win.inFreeformWindowingMode()) {// 如果窗口是自由窗口,并且窗口和導航欄重疊mIsFreeformWindowOverlappingWithNavBar = true;}if (!affectsSystemUi) {return;}...代碼省略...}}

💡 技術無價,贊賞隨心

寫文不易,如果本文幫你避開了“八小時踩坑”,或者讓你直呼“學到了!”
歡迎掃碼贊賞,讓我知道這篇內容值得!

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

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

相關文章

C# 將HTML文檔、HTML字符串轉換為圖片

在.NET開發中&#xff0c;將HTML內容轉換為圖片的需求廣泛存在于報告生成、郵件內容存檔、網頁快照等場景。Free Spire.Doc for .NET作為一款免費的專業文檔處理庫&#xff0c;無需Microsoft Word依賴&#xff0c;即可輕松實現這一功能。本文將深入解析HTML文檔和字符串轉圖片兩…

【HTML-15.2】HTML表單按鈕全面指南:從基礎到高級實踐

表單按鈕是網頁交互的核心元素&#xff0c;作為用戶提交數據、觸發操作的主要途徑&#xff0c;其重要性不言而喻。本文將系統性地介紹HTML表單按鈕的各種類型、使用場景、最佳實踐以及高級技巧&#xff0c;幫助開發者構建更高效、更易用的表單交互體驗。 1. 基礎按鈕類型 1.1…

吳恩達MCP課程(4):connect_server_mcp_chatbot

目錄 完整代碼代碼解釋1. 導入和初始化2. 類型定義3. MCP_ChatBot 類初始化4. 查詢處理 (process_query)5. 服務器連接管理6. 核心特性總結 示例 完整代碼 原課程代碼是用Anthropic寫的&#xff0c;下面代碼是用OpenAI改寫的&#xff0c;模型則用阿里巴巴的模型做測試 .env 文…

C++內存學習

引入 在實例化對象時&#xff0c;不管是編譯器還是我們自己&#xff0c;會使用構造函數給成員變量一個合適的初始值。 但是經過構造函數之后&#xff0c;我們還不能將其稱為成員變量的初始化&#xff1a; 構造函數中的語句只能稱為賦初值&#xff0c;而不能稱作初始化 因為初…

MySQL 大戰 PostgreSQL

一、底層架構對比 ??維度????MySQL????PostgreSQL????存儲引擎??多引擎支持&#xff08;InnoDB、MyISAM等&#xff09;單一存儲引擎&#xff08;支持擴展如Zheap、Zedstore&#xff09;??事務實現??基于UNDO日志的MVCC基于堆表(Heap)的MVCC??鎖機制??…

基于FPGA的二叉決策樹cart算法verilog實現,訓練環節采用MATLAB仿真

目錄 1.算法運行效果圖預覽 2.算法運行軟件版本 3.部分核心程序 4.算法理論概述 5.算法完整程序工程 1.算法運行效果圖預覽 (完整程序運行后無水印) MATLAB訓練結果 上述決策樹判決條件&#xff1a; 分類的決策樹1 if x21<17191.5 then node 2 elseif x21>17191…

【RAG】RAG綜述|一文了解RAG|從零開始(下)

文章目錄 5. RAG的架構5.1 Naive RAG5.2 Advanced RAG5.2.1 檢索前處理和數據索引技術5.2.2 知識分片技術5.2.3 分層索引5.2.4 檢索技術5.2.4.1 優化用戶查詢5.2.4.2 通過假想文檔嵌入修復查詢和文檔不對稱5.2.4.3 Routing5.2.4.5 自查詢檢索5.2.4.6 混合搜索5.2.4.7 圖檢索5.2…

山東大學軟件學院項目實訓-基于大模型的模擬面試系統-面試官和面試記錄的分享功能(2)

本文記錄在發布文章時&#xff0c;可以添加自己創建的面試官和面試記錄到文章中這一功能的實現。 前端 首先是在原本的界面的底部添加了兩個多選框&#xff08;后期需要美化調整&#xff09; 實現的代碼&#xff1a; <el-col style"margin-top: 1rem;"><e…

FPGA純verilog實現MIPI-DSI視頻編碼輸出,提供工程源碼和技術支持

目錄 1、前言工程概述免責聲明 2、相關方案推薦我已有的所有工程源碼總目錄----方便你快速找到自己喜歡的項目我這里已有的 MIPI 編解碼方案 3、設計思路框架工程設計原理框圖FPGA內部彩條RGB數據位寬轉換RGB數據緩存MIPI-DSI協議層編碼MIPI-DPHY物理層串化MIPI-LVDS顯示屏工程…

LXQt修改開始菜單高亮

開始菜單紅色高亮很難看 mkdir -p ~/.local/share/lxqt/palettes/ mkdir -p ~/.local/share/lxqt/themes/ cp /usr/share/lxqt/palettes/Dark ~/.local/share/lxqt/palettes/Darker cp -p /usr/share/lxqt/themes/dark ~/.local/share/lxqt/themes/darker lxqt-panel.qss L…

DeepSeek-R1-0528-Qwen3-8B 本地ollama離線運行使用和llamafactory lora微調

參考: https://huggingface.co/deepseek-ai/DeepSeek-R1-0528-Qwen3-8B 量化版本: https://huggingface.co/unsloth/DeepSeek-R1-0528-Qwen3-8B-GGUF https://docs.unsloth.ai/basics/deepseek-r1-0528-how-to-run-locally 1、ollama運行 升級ollama版本到0.9.0 支持直接…

vue3 + WebSocket + Node 搭建前后端分離項目 開箱即用

[TOC](vue3 WebSocket Node 搭建前后端分離項目) 開箱即用 前言 top1&#xff1a;vue3.5搭建前端H5 top2&#xff1a;Node.js koa搭建后端服務接口 top3&#xff1a;WebSocket 長連接實現用戶在線聊天 top4&#xff1a;接口實現模塊化 Mysql 自定義 top5&#xff1a;文件上…

Vue 前端代碼規范實戰:ESLint v9、Prettier 與 Stylelint 集成指南與最佳實踐

&#x1f680; 作者主頁&#xff1a; 有來技術 &#x1f525; 開源項目&#xff1a; youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template &#x1f33a; 倉庫主頁&#xff1a; GitCode︱ Gitee ︱ Github &#x1f496; 歡迎點贊 &#x1f44d; 收藏 ?評論 …

docker docker-ce docker.io

Ubuntu安裝 ??更新軟件包列表?? 首先確保軟件包列表是最新的&#xff1a; sudo apt-get update 使用正確的卸載命令?? 替換 docker-engine 為 docker-ce 或 docker.io&#xff1a; sudo apt-get remove docker docker-ce docker.io containerd runc ??檢查已安裝的 Do…

C++ 初階 | 類和對象易錯知識點(下)

目錄 0.引言 1.初始化列表 2.static 靜態成員變量&#xff1a; 靜態成員函數&#xff1a; 3.友元函數 4.內部類 定義&#xff1a; 特點&#xff1a; 應用&#xff1a; 5.優化寫法 6.例題 求和12...n (不能用for/while/if/else等關鍵字) 7.總結 0.引言 今天&…

使用yocto搭建qemuarm64環境

環境 yocto下載 # 源碼下載 git clone git://git.yoctoproject.org/poky git reset --hard b223b6d533a6d617134c1c5bec8ed31657dd1268 構建 # 編譯鏡像 export MACHINE"qemuarm64" . oe-init-build-env bitbake core-image-full-cmdline 運行 # 跑虛擬機 export …

AWS WebRTC:獲取ICE服務地址(part 3):STUN服務和TURN服務的作用

STUN服務和TURN服務的作用&#xff1a; 服務全稱作用是否中繼流量適用場景STUNSession Traversal Utilities for NAT 協助設備發現自己的公網地址&#xff08;srflx candidate&#xff09; ? 不中繼&#xff0c;僅輔助NAT 穿透成功時使用TURNTraversal Using Relays around N…

分析XSSstrike源碼

#用于學習web安全自動化工具# 我能收獲什么&#xff1f; 1.XSS漏洞檢測機制 學習如何構造和發送XSS payload如何識別響應中的回顯&#xff0c;WAF&#xff0c;過濾規則等如何使用詞典&#xff0c;編碼策略&#xff0c;上下文探測等繞過過濾器 2.Python安全工具開發技巧 使…

npm run build 報錯:Some chunks are larger than 500 KB after minification

當我們的 Vue 項目太大&#xff0c;使用 npm run build 打包項目的時候&#xff0c;就有可能會遇到以下報錯&#xff1a; (!) Some chunks are larger than 500 kB after minification. Consider: - Using dynamic import() to code-split the application - Use build.rollup…

【LLM相關知識點】關于LLM項目實施流程的簡單整理(一)

【LLM相關知識點】關于LLM項目實施流程的簡單整理&#xff08;一&#xff09; 文章目錄 【LLM相關知識點】關于LLM項目實施流程的簡單整理&#xff08;一&#xff09;零、學習計劃梳理&#xff1a;結合ChatGPT從零開始學習LLM & 多模態大模型一、大模型相關應用場景和頭部企…