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.mzph.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]) 本题其实很容易…