Android 13.0 MTK Camera2 設置默認拍照尺寸功能實現

Android 13.0 MTK Camera2 設置默認拍照尺寸功能實現

文章目錄

  • 需求:
  • 參考資料
    • 架構圖了解
    • Camera相關專欄
    • 零散知識了解
    • 部分相機源碼參考,學習API使用,梳理流程,偏應用層
    • Camera2 系統相關
  • 修改文件-修改方案
    • 修改文件:
    • 修改內容:
      • PictureSize.java onValueInitialized 方法
      • PictureSizeHelper.java getCustomDefault 方法
  • 源碼分析
    • 設置拍照尺寸的核心類
    • 源碼逐步分析
      • 關聯的照片大小搜索
      • PictureSizeSelector
        • 進入界面選中的邏輯
        • 點擊選中圖片大小邏輯
      • PictureSizeSelectorPreference
      • PictureSizeSettingView
        • onItemClick
        • onPreferenceClick
      • PictureSize
        • onValueInitialized
  • 總結


需求:

默認相機拍照尺寸

需求原因
1)客戶自身喜好
2)部分客戶自己的攝像頭不兼容,比如拍照尺寸太大會卡頓,拉絲等現象

在這里插入圖片描述

參考資料

Android 13.0 MTK Camera2 設置默認拍照尺寸功能實現
Android 11.0 MTK Camera2 設置默認拍照尺寸功能實現

這兩篇文章介紹的蠻好的,可以看看,對于類似需求同理也可以按照改一改? 為什么有些會默認最高分辨率拍照,可能原因在于手機端產品為了最好的拍攝效果,尺寸會默認到最大。

對于Camera2 開發,遇到的困難點就是源碼代碼量太多,對于很多同事來說就是一臉懵逼,建議多積累一定的代碼量,掌握基本的知識。

架構圖了解

MTKCamera2相機架構
Camera2架構
Android Camera架構簡析

Camera相關專欄

Camera Framework 專欄
小馳私房菜系列
小馳私房菜MTK系列
小馳Camera 開發系列
Camera 相機開發
展訊平臺 Camera
官方文檔:谷歌官方 API 描述

零散知識了解

MTK 相機UI介紹
Camera2 相機認知
Camera2學習筆記
camera2關于拍照預覽方向旋轉90度和拍照圖片鏡像功能實現
Camera2 預覽集成、簡單拍照:熟悉預覽步驟流程比較有用
Camera鏡像上下左右顛倒問題的解決辦法
MTK相機成像質量差
Camera應用分析

部分相機源碼參考,學習API使用,梳理流程,偏應用層

極客相機 Camera2 API
Camera2 API詳解
極客相機源碼
Camera2 相機Demo
Camera2 專業相機Demo
拍照、預覽、錄像Demo
使用Camera2 拍照

Camera2 系統相關

Camera2 Service 啟動

修改文件-修改方案

修改文件:

\vendor\mediatek\proprietary\packages\apps\Camera2\feature\setting\picturesize\src\com\mediatek\camera\feature\setting\picturesize\PictureSize.java\vendor\mediatek\proprietary\packages\apps\Camera2\feature\setting\picturesize\src\com\mediatek\camera\feature\setting\picturesize\PictureSizeHelper.java

修改內容:

PictureSize.java onValueInitialized 方法

在 onValueInitialized 方法中,默認valueInStore 中調用PictureSizeHelper 類中自定義的 getCustomDefault 方法

         if (valueInStore == null) {// Default picture size is the max full-ratio size.
-            List<String> entryValues = getEntryValues();
+                       LogHelper.d(TAG, "valueInStore == null  Default picture size is the max full-ratio size:");
+            /*List<String> entryValues = getEntryValues();for (String value : entryValues) {if (PictureSizeHelper.getStandardAspectRatio(value) == fullRatio) {valueInStore = value;
+                                       LogHelper.d(TAG, "valueInStore == null:valueInStore:"+valueInStore);break;}
-            }
+            }*/
+                        valueInStore =PictureSizeHelper.getCustomDefault(getEntryValues());
+                       }

PictureSizeHelper.java getCustomDefault 方法

自定義 getCustomDefault 方法,設置默認分辨率。 這里直接寫死,或者 根據客需要求設置為最大、最小 等。

    public static String getCustomDefault(List<String> supportedEntryValues){for (int i=0;i< supportedEntryValues.size();i++) {   /*Size size = valueToSize(supportedEntryValues.get(i));temp = size.width * size.height;        if (temp > maxSize) {maxSize = temp;maxIndex = i;}*/LogHelper.d(TAG,   "getCustomDefault:" +supportedEntryValues.get(i));}return  "1920x1088";}

源碼分析

設置拍照尺寸的核心類

\vendor\mediatek\proprietary\packages\apps\Camera2\feature\setting\picturesize\src\com\mediatek\camera\feature\setting\picturesize\PictureSize.java
\vendor\mediatek\proprietary\packages\apps\Camera2\feature\setting\picturesize\src\com\mediatek\camera\feature\setting\picturesize\PictureSizeHelper.java
\vendor\mediatek\proprietary\packages\apps\Camera2\feature\setting\picturesize\src\com\mediatek\camera\feature\setting\picturesize\PictureSizeSettingView.java

源碼逐步分析

關聯的照片大小搜索

grep -rn 照片大小

在這里插入圖片描述
找到如下路徑相關關鍵字:照片大小

feature/mode/vsdof/res/values-zh-rCN/strings.xml
<string name="sdof_picture_size_title">"照片大小"</string>feature/setting/picturesize/res/values-zh-rCN/strings.xml<string name="pref_camera_picturesize_title">"照片大小"</string>

PictureSizeSelector

上面已經找到了兩個關鍵字,這里先根據第一個關鍵字找一下源碼:
路徑:

/vendor/mediatek/proprietary/packages/apps/Camera2/feature/setting/picturesize/src/com/mediatek/camera/feature/setting/picturesize/PictureSizeSelector.java
R.string.pref_camera_picturesize_title

在這里插入圖片描述

我們看類定義:


/*** Picture size selector.*/public class PictureSizeSelector extends PreferenceFragment {

就是圖片大小選擇器
對應的是如下界面:
在這里插入圖片描述
既然是這個界面,那就看一下點擊選中方法和進入這個界面的設置方法

進入界面選中的邏輯

這里關聯的有四個方法,對應的進入界面選中邏輯:

@Overridepublic void onCreate(Bundle savedInstanceState) {LogHelper.d(TAG, "[onCreate]");super.onCreate(savedInstanceState);prepareValuesOnShown();Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);if (toolbar != null) {toolbar.setTitle(getActivity().getResources().getString(R.string.pref_camera_picturesize_title));}addPreferencesFromResource(R.xml.picturesize_selector_preference);PreferenceScreen screen = getPreferenceScreen();for (int i = 0 ; i < mEntryValues.size(); i++) {RadioPreference preference = new RadioPreference(getActivity());if (mEntryValues.get(i).equals(mSelectedValue)) {preference.setChecked(true);}LogHelper.d(TAG," onCreate  ->mEntryValues.get(i):"+mEntryValues.get(i));preference.setTitle(mTitleList.get(i));preference.setSummary(mSummaryList.get(i));preference.setOnPreferenceClickListener(mOnPreferenceClickListener);screen.addPreference(preference);}}/*** Set the default selected value.** @param value The default selected value.*/public void setValue(String value) {LogHelper.d(TAG,"  setValue: value->"+value);mSelectedValue = value;}/*** Set the picture sizes supported.** @param entryValues The picture sizes supported.*/public void setEntryValues(List<String> entryValues) {mEntryValues.clear();mEntryValues.addAll(entryValues);}private void prepareValuesOnShown() {List<String> tempValues = new ArrayList<>(mEntryValues);mEntryValues.clear();mTitleList.clear();mSummaryList.clear();for (int i = 0; i < tempValues.size(); i++) {String value = tempValues.get(i);String title = PictureSizeHelper.getPixelsAndRatio(value);LogHelper.d(TAG,"  prepareValuesOnShown: value->"+value+"     title:"+title);if (title != null) {mTitleList.add(title);mEntryValues.add(value);mSummaryList.add(value);}else{LogHelper.d(TAG, "[prepareValuesOnShown] value :"+value+" will not shown.");}}}
方法作用
setEntryValues設置支持的圖片大小 分辨率
prepareValuesOnShown準備顯示的數據 在onCreate 方法里面調用的
setValue設置默認選擇的值
onCreate通過setEntryValue 設置的集合,遍歷創建PreferenceScreen ,對于傳遞進來的value 作為選中效果
點擊選中圖片大小邏輯

對于點擊邏輯更為簡單,回調 返回上一層,代碼如下:

   private class MyOnPreferenceClickListener implements Preference.OnPreferenceClickListener {@Overridepublic boolean onPreferenceClick(Preference preference) {String summary = (String) preference.getSummary();int index = mSummaryList.indexOf(summary);String value = mEntryValues.get(index);mListener.onItemClick(value);LogHelper.d(TAG,"  MyOnPreferenceClickListener: onPreferenceClick  value->"+value);mSelectedValue = value;getActivity().getFragmentManager().popBackStack();return true;}}

PictureSizeSelectorPreference

同 PictureSizeSelector 上面已經找到了兩個關鍵字,這里先根據第二個關鍵字找一下源碼:
路徑:

./vendor/mediatek/proprietary/packages/apps/Camera2/feature/mode/aicombo/src/com/mediatek/camera/feature/mode/aicombo/photo/view/PictureSizeSelectorPreference.java
./vendor/mediatek/proprietary/packages/apps/Camera2/feature/mode/vsdof/src/com/mediatek/camera/feature/mode/vsdof/photo/view/PictureSizeSelectorPreference.java看源碼發現和 PictureSizeSelector 代碼基本一致 ,但是仔細看一個方法的說明如下:/*** Set the video quality supported.* @param entryValues The video quality supported.*/public void setEntryValues(List<String> entryValues) {mEntryValues.clear();mEntryValues.addAll(entryValues);}這些事設置Vieo 的  并不是設置picture 的。 所以我們需求設置圖片質量的其實應該是上面找到的 PictureSizeSelector 

PictureSizeSettingView

路徑:

/vendor/mediatek/proprietary/packages/apps/Camera2/feature/setting/picturesize/src/com/mediatek/camera/feature/setting/picturesize/PictureSizeSettingView.java

找到這個類的方法有兩種

  • grep 查找關鍵字 “照片大小”
  • 根據上面定位到的源碼 PictureSizeSelector

就是進入到 PictureSizeSelector 界面之前的頁面,如下:
在這里插入圖片描述
準確的來說, PictureSizeSettingView 對應的其實是這個界面中 圖片大小的這個item .
源碼代碼量不多,我們賦上來看看:

package com.mediatek.camera.feature.setting.picturesize;import android.app.Activity;
import android.app.FragmentTransaction;
import android.preference.PreferenceFragment;import com.mediatek.camera.R;
import com.mediatek.camera.common.debug.LogHelper;
import com.mediatek.camera.common.debug.LogUtil;
import com.mediatek.camera.common.preference.Preference;
import com.mediatek.camera.common.setting.ICameraSettingView;import java.util.ArrayList;
import java.util.List;/*** Picture size setting view.*/
public class PictureSizeSettingView implements ICameraSettingView,PictureSizeSelector.OnItemClickListener {private static final LogUtil.Tag TAG =new LogUtil.Tag(PictureSizeSettingView.class.getSimpleName());private Activity mActivity;private Preference mPref;private OnValueChangeListener mListener;private String mKey;private String mSelectedValue;private List<String> mEntryValues = new ArrayList<>();private String mSummary;private PictureSizeSelector mSizeSelector;private boolean mEnabled;/*** Listener to listen picture size value changed.*/public interface OnValueChangeListener {/*** Callback when picture size value changed.** @param value The changed picture size, such as "1920x1080".*/void onValueChanged(String value);}/*** Picture size setting view constructor.** @param key The key of picture size.*/public PictureSizeSettingView(String key) {mKey = key;}@Overridepublic void loadView(PreferenceFragment fragment) {LogHelper.d(TAG, "[loadView]");mActivity = fragment.getActivity();if (mSizeSelector == null) {mSizeSelector = new PictureSizeSelector();mSizeSelector.setOnItemClickListener(this);}fragment.addPreferencesFromResource(R.xml.picturesize_preference);mPref = (Preference) fragment.findPreference(mKey);mPref.setRootPreference(fragment.getPreferenceScreen());mPref.setId(R.id.picture_size_setting);mPref.setContentDescription(mActivity.getResources().getString(R.string.picture_size_content_description));mPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {@Overridepublic boolean onPreferenceClick(android.preference.Preference preference) {mSizeSelector.setValue(mSelectedValue);mSizeSelector.setEntryValues(mEntryValues);FragmentTransaction transaction = mActivity.getFragmentManager().beginTransaction();transaction.addToBackStack(null);transaction.replace(R.id.setting_container,mSizeSelector, "picture_size_selector").commit();return true;}});mPref.setEnabled(mEnabled);if (mSelectedValue != null) {mSummary = PictureSizeHelper.getPixelsAndRatio(mSelectedValue);}}@Overridepublic void refreshView() {if (mPref != null) {LogHelper.d(TAG, "[refreshView]");mPref.setSummary(mSummary);mPref.setEnabled(mEnabled);}}@Overridepublic void unloadView() {LogHelper.d(TAG, "[unloadView]");}@Overridepublic void setEnabled(boolean enabled) {mEnabled = enabled;}@Overridepublic boolean isEnabled() {return mEnabled;}/*** Set listener to listen the changed picture size value.** @param listener The instance of {@link OnValueChangeListener}.*/public void setOnValueChangeListener(OnValueChangeListener listener) {mListener = listener;}/*** Set the default selected value.** @param value The default selected value.*/public void setValue(String value) {mSelectedValue = value;}/*** Set the picture sizes supported.** @param entryValues The picture sizes supported.*/public void setEntryValues(List<String> entryValues) {mEntryValues = entryValues;}@Overridepublic void onItemClick(String value) {mSelectedValue = value;mSummary = PictureSizeHelper.getPixelsAndRatio(value);if (mListener != null) {mListener.onValueChanged(value);}}
}
onItemClick

這里關注下這個 onItemClick 點擊方法,我們看類聲明如下:

PictureSizeSettingView implements ICameraSettingView,PictureSizeSelector.OnItemClickListener

所以 這個 onItemClick 方法其實是PictureSizeSelector 類的點擊方法的回調。

onPreferenceClick

先看源碼,如下:

  mPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {@Overridepublic boolean onPreferenceClick(android.preference.Preference preference) {mSizeSelector.setValue(mSelectedValue);mSizeSelector.setEntryValues(mEntryValues);FragmentTransaction transaction = mActivity.getFragmentManager().beginTransaction();transaction.addToBackStack(null);transaction.replace(R.id.setting_container,mSizeSelector, "picture_size_selector").commit();return true;}});

這個方法其實就做了三件事情:

  • setValue 設置默認圖片大小
  • setEntryValues 設置支持的所有圖片大小集合
  • transaction.replace 操作,跳轉到PictureSizeSelector 界面
    這里其實就和PictureSizeSelector 完全關聯起來了。

接下來就要關注 兩個事情:

  • mListener.onValueChanged(value); 在哪里設置回調的
  • setValue 這個類里面也有設置默認圖片大小,到底在哪里設置的

PictureSize

源碼路徑:

/vendor/mediatek/proprietary/packages/apps/Camera2/feature/setting/picturesize/src/com/mediatek/camera/feature/setting/picturesize/PictureSize.java

如何關聯到這個類?
上面已經分析到了 PictureSizeSettingView 的 onValueChanged,其實就是要找 PictureSizeSettingView 中 接口 OnValueChangeListener 是在哪里實現的,這樣來找到具體的實現和調用地方。

先看類說明:
這里我們看下部分代碼片段截圖:
在這里插入圖片描述
上面截圖就可以基本確認了,它對應的界面才是 照片設置圖,如下:
在這里插入圖片描述

onValueInitialized

源代碼如下:

 /*** Invoked after setting's all values are initialized.** @param supportedPictureSize Picture sizes which is supported in current platform.*/public void onValueInitialized(List<String> supportedPictureSize) {LogHelper.d(TAG, "[onValueInitialized], supportedPictureSize:" + supportedPictureSize);double fullRatio = PictureSizeHelper.findFullScreenRatio(mActivity);List<Double> desiredAspectRatios = new ArrayList<>();desiredAspectRatios.add(fullRatio);desiredAspectRatios.add(PictureSizeHelper.RATIO_4_3);PictureSizeHelper.setDesiredAspectRatios(desiredAspectRatios);PictureSizeHelper.setFilterParameters(DEGRESSIVE_RATIO, MAX_COUNT);if (sFilterPictureSize) {supportedPictureSize = PictureSizeHelper.filterSizes(supportedPictureSize);LogHelper.d(TAG, "[onValueInitialized], after filter, supportedPictureSize = "+ supportedPictureSize);}if (FILTER_MODE.equals(mModeKey)|| VFB_MODE.equals(mModeKey)|| FB_MODE.equals(mModeKey)) {//for low romif ((VFB_MODE.equals(mModeKey)||FILTER_MODE.equals(mModeKey))&& isLowRam()) {List<String> supportedPictureSizeAfterCheck = new ArrayList<String>();for (String pictureSize : supportedPictureSize) {String[] size = pictureSize.split("x");int width = Integer.parseInt(size[0]);int height = Integer.parseInt(size[1]);if (width < PICTURE_SIZE_9M_WIDTH&& height < PICTURE_SIZE_9M_HEIGHT) {supportedPictureSizeAfterCheck.add(pictureSize);}}supportedPictureSize = supportedPictureSizeAfterCheck;LogHelper.d(TAG, "[onValueInitialized], low ram, after check, " +"supportedPictureSize:"+ supportedPictureSize);} else {List<String> supportedPictureSizeAfterCheck = new ArrayList<String>();for (String pictureSize : supportedPictureSize) {String[] size = pictureSize.split("x");int width = Integer.parseInt(size[0]);int height = Integer.parseInt(size[1]);if (width <= PictureSizeHelper.getMaxTexureSize()&& height <= PictureSizeHelper.getMaxTexureSize()) {supportedPictureSizeAfterCheck.add(pictureSize);}}supportedPictureSize = supportedPictureSizeAfterCheck;LogHelper.d(TAG, "[onValueInitialized], GPU Mode, after check, " +"supportedPictureSize:"+ supportedPictureSize);}}if (HDR_MODE.equals(mModeKey)) {List<String> supportedPictureSizeAfterCheck = new ArrayList<String>();for (String pictureSize : supportedPictureSize) {for (String yuvSize:mYUVsupportedSize){if(pictureSize.equals(yuvSize)){supportedPictureSizeAfterCheck.add(pictureSize);}}}supportedPictureSize=supportedPictureSizeAfterCheck;LogHelper.d(TAG, "[onValueInitialized], PostAlgo Mode, after check, supportedPictureSize:"+ supportedPictureSize);}if (AIBEAUTYPHOTO_MODE.equals(mModeKey)|| AIBOKEHPHOTO_MODE.equals(mModeKey)|| AICOLORPHOTO_MODE.equals(mModeKey)|| AILEGGYPHOTO_MODE.equals(mModeKey)|| AISLIMMINGPHOTO_MODE.equals(mModeKey)) {List<String> supportedPictureSizeAfterCheck = new ArrayList<String>();for (String pictureSize : supportedPictureSize) {String[] size = pictureSize.split("x");int width = Integer.parseInt(size[0]);int height = Integer.parseInt(size[1]);if (width <= PictureSizeHelper.getMaxTexureSize()&& height <= PictureSizeHelper.getMaxTexureSize()) {supportedPictureSizeAfterCheck.add(pictureSize);}}supportedPictureSize = supportedPictureSizeAfterCheck;LogHelper.d(TAG, "[onValueInitialized], mModeKey:" + mModeKey + ",after check, supportedPictureSize:"+ supportedPictureSize);}setSupportedPlatformValues(supportedPictureSize);setSupportedEntryValues(supportedPictureSize);setEntryValues(supportedPictureSize);refreshViewEntry();String valueInStore = mDataStore.getValue(getKey(), null, getStoreScope());if (valueInStore != null&& !supportedPictureSize.contains(valueInStore)) {LogHelper.d(TAG, "[onValueInitialized], value:" + valueInStore+ " isn't supported in current platform");valueInStore = null;mDataStore.setValue(getKey(), null, getStoreScope(), false);}if (valueInStore == null) {// Default picture size is the max full-ratio size.LogHelper.d(TAG, "valueInStore == null  Default picture size is the max full-ratio size:");/*List<String> entryValues = getEntryValues();for (String value : entryValues) {if (PictureSizeHelper.getStandardAspectRatio(value) == fullRatio) {valueInStore = value;LogHelper.d(TAG, "valueInStore == null:valueInStore:"+valueInStore);break;}}*/valueInStore =PictureSizeHelper.getCustomDefault(getEntryValues());}// If there is no full screen ratio picture size, use the first value in// entry values as the default value.if (valueInStore == null) {valueInStore = getEntryValues().get(0);LogHelper.d(TAG, "valueInStore:valueInStore:"+valueInStore);}setValue(valueInStore);}

看方法注釋就一目了然了,根據當前平臺設置-初始化圖片大小

 /*** Invoked after setting's all values are initialized.** @param supportedPictureSize Picture sizes which is supported in current platform.*/

對于 valueInStore 的具體設置內容和關聯邏輯,這里暫不分析。

總結

  • 實現了MTK Android13 平臺下默認圖片大小的邏輯
  • 分析了解決問題的思路,源碼分析流程
  • 建議對Camera2 相關知識需要一定的了解最好
  • 在查看源碼的過程中,難免找不到關鍵字,不知道修改哪里。 可以借助IDE- AS VS 操作,方便定位源碼位置。

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

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

相關文章

HarmonyOS 框架基礎知識

參考文檔&#xff1a;HarmonyOS開發者文檔 第三方庫&#xff1a;OpenHarmony三方庫中心倉 基礎特性 Entry&#xff1a;關鍵裝飾器 Components&#xff1a;組件 特性EntryComponent??作用范圍僅用于頁面入口可定義任意可復用組件??數量限制??每個頁面有且僅有一個無數量…

前端分頁與瀑布流最佳實踐筆記 - React Antd 版

前端分頁與瀑布流最佳實踐筆記 - React Antd 版 1. 分頁與瀑布流對比 分頁&#xff08;Pagination&#xff09;瀑布流&#xff08;Infinite Scroll&#xff09;展示方式按頁分批加載&#xff0c;有明確頁碼控件滾動到底部時自動加載更多內容&#xff0c;無明顯分頁用戶控制用…

Linux網絡編程:TCP多進程/多線程并發服務器詳解

Linux網絡編程&#xff1a;TCP多進程/多線程并發服務器詳解 TCP并發服務器概述 在Linux網絡編程中&#xff0c;TCP服務器主要有三種并發模型&#xff1a; 多進程模型&#xff1a;為每個客戶端連接創建新進程多線程模型&#xff1a;為每個客戶端連接創建新線程I/O多路復用&am…

詳解springcloudalibaba采用prometheus+grafana實現服務監控

文章目錄 1.官網下載安裝 prometheus和grafana1.promethus2.grafana 2. 搭建springcloudalibaba集成prometheus、grafana1. 引入依賴,springboot3.2之后引入如下2. 在yml文件配置監控端點暴露配置3. 在當前啟動的應用代碼中添加&#xff0c;在prometheus顯示的時候附加當前應用…

數據分析1

一、常用數據處理模塊Numpy Numpy常用于高性能計算&#xff0c;在機器學習常常作為傳遞數據的容器。提供了兩種基本對象&#xff1a;ndarray、ufunc。 ndarray具有矢量算術運算和復雜廣播能力的快速且節省空間的多維數組。 ufunc提供了對數組快速運算的標準數學函數。 ndar…

DeepSeek智能時空數據分析(六):大模型NL2SQL繪制城市之間連線

序言&#xff1a;時空數據分析很有用&#xff0c;但是GIS/時空數據庫技術門檻太高 時空數據分析在優化業務運營中至關重要&#xff0c;然而&#xff0c;三大挑戰仍制約其發展&#xff1a;技術門檻高&#xff0c;需融合GIS理論、SQL開發與時空數據庫等多領域知識&#xff1b;空…

2023ICPC合肥題解

文章目錄 F. Colorful Balloons(簽到)E. Matrix Distances(思維小結論)J. Takeout Delivering(最短路)G. Streak Manipulation(二分dp)C. Cyclic Substrings(回文自動機) 題目鏈接 F. Colorful Balloons(簽到) int n;cin>>n;for(int i1;i<n;i) cin>>s[i];map<…

數字技術驅動下教育生態重構:從信息化整合到數字化轉型的路徑探究

一、引言 &#xff08;一&#xff09;研究背景與問題提出 在當今時代&#xff0c;數字技術正以前所未有的速度和深度滲透到社會的各個領域&#xff0c;教育領域也不例外。從早期的教育信息化整合到如今的數字化轉型&#xff0c;教育系統正經歷著一場深刻的范式變革。 回顧教…

terraform 動態塊(Dynamic Blocks)詳解與實踐

在 Terraform 中&#xff0c;動態塊&#xff08;Dynamic Blocks&#xff09; 是一種強大的機制&#xff0c;允許你根據變量或表達式動態生成配置塊&#xff0c;避免重復編寫相似的代碼。這在處理需要重復定義的結構&#xff08;如資源參數、嵌套配置&#xff09;時特別有用。以…

Unity3D引擎框架及用戶接口調用方式相關分析及匯總

分析目的 目前外網3D手游絕大部基于Unity3D引擎進行開發,Unity3D引擎屬于商業引擎,引擎整理框架的運行機制較為神秘,本文介紹Unity引擎框架、對象組織方式、用戶接口與引擎交互方式等原理,通過本文的分析和介紹可了解Unity3D框架中大致執行原理。 實現原理 Unity引擎作為…

react-09React生命周期

1.react生命周期&#xff08;舊版&#xff09; 1.1react初始掛載時的生命周期 1:構造器-constructor // 構造器constructor(props) {console.log(1:構造器-constructor);super(props)// 初始化狀態this.state {count: 0}} 2:組件將要掛載-componentWillMount // 組件將要掛載…

【NVM】管理不同版本的node.js

目錄 一、下載nvm 二、安裝nvm 三、驗證安裝 四、配置下載鏡像 五、使用NVM 前言&#xff1a;不同的node.js版本會讓你在使用過程很費勁&#xff0c;nvm是一個node版本管理工具&#xff0c;通過它可以安裝多種node版本并且可以快速、簡單的切換node版本。 一、下載nvm htt…

八大排序——冒泡排序/歸并排序

八大排序——冒泡排序/歸并排序 一、冒泡排序 1.1 冒泡排序 1.2 冒泡排序優化 二、歸并排序 1.1 歸并排序&#xff08;遞歸&#xff09; 1.2 遞歸排序&#xff08;非遞歸&#xff09; 一、冒泡排序 1.1 冒泡排序 比較相鄰的元素。如果第一個比第二個大&#xff0c;就交換…

區塊鏈隨學隨記

前情提要&#xff1a;本人技術棧為ganachehardhatpython ganache提供的是本地的區塊鏈環境&#xff0c;相當于模擬以太坊&#xff0c;這樣可以允許多個賬戶在本機交互。hardhat和remix都是區塊鏈ide&#xff0c;用于編寫和部署合約助記詞有個數規定&#xff0c;只有滿足這些個數…

Android原生開發基礎

Android實戰 Android 原生開發基礎 知識點1 介紹了解2 系統體系架構3 四大應用組件4 移動操作系統優缺點5 開發工具6 配置工具7 下載相關資源8JDK下載安裝流程9配置好SDK和JDK環境10 第一個Hello word11 AS開發前常用設置12模擬器使用運行13 真機調試14 AndroidUI基礎布局15 加…

網頁版 deepseek 對話問答內容導出為 PDF 文件和 Word 文件的瀏覽器插件下載安裝和使用說明

文章目錄 網頁版 deepseek 瀏覽器擴展應用程序插件1. 預覽效果2. 功能介紹3. 瀏覽器擴展應用程序下載3.1. 下載方式13.2. 下載方式24. 安裝教程4.1. Chrome 瀏覽器安裝步驟4.2. Edge 瀏覽器安裝步驟5. 使用說明網頁版 deepseek 瀏覽器擴展應用程序插件 1. 預覽效果 預覽效果 導…

DBdriver使用taos數據庫

首先創建連接 連接后比如數據庫里有三個庫 選擇其中的hypon 選中localhost&#xff0c;右鍵sql編輯器&#xff0c;打開sql控制臺 就插入了一條數據

【前端】【面試】如何實現圖片漸進式加載?有幾種方法

前端圖片漸進式加載 一、技術原理解析 漸進式加載是通過分階段、按需加載圖片&#xff0c;以提升用戶體驗和頁面性能的優化技術。主要包括以下實現方式&#xff1a; 懶加載&#xff1a;基于IntersectionObserver API&#xff0c;當圖片進入瀏覽器視口時才發起加載請求&#…

Spring Boot 中的條件注解

Spring Boot條件注解的匯總&#xff1a; 注解作用判斷依據使用場景ConditionalOnBean容器中存在指定Bean時&#xff0c;被注解的配置或Bean定義生效指定Bean在容器中存在依賴其他已存在Bean時配置相關功能ConditionalOnCheckpointRestore在特定檢查點恢復相關條件滿足時生效滿…

leetcode11-盛水最多的容器

leetcode 11 思路 問題分析 拆解問題&#xff0c;面積 底 * 高 寬度&#xff1a;兩個豎直線之間的距離&#xff0c;顯然是 right - left高度&#xff1a;容器的水位受限于較短的那根豎直線的高度&#xff0c;所以高度為 min(height[left], height[right]) 本題其實很容易…