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

Android 10.0 Settings 加载流程

一、系统设置首页

代码路径:packages/app/Settings/

1 主界面加载:
    <!-- Alias for launcher activity only, as this belongs to each profile. --><activity-alias android:name="Settings"android:label="@string/settings_label_launcher"android:launchMode="singleTask"android:targetActivity=".homepage.SettingsHomepageActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.DEFAULT" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter><meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts"/></activity-alias>

Settings的主界面是Settings.java,但是从Settings.java来看,除了大量的静态类继承SettingsActivity,就无其他有效信息了。但看其xml定义可以发现targetActivity属性,实质应是SettingsHomepageActivity.java。
先看其xml配置:

        <activity android:name=".homepage.SettingsHomepageActivity"android:label="@string/settings_label_launcher"android:theme="@style/Theme.Settings.Home"android:launchMode="singleTask"><intent-filter android:priority="1"><action android:name="android.settings.SETTINGS" /><category android:name="android.intent.category.DEFAULT" /></intent-filter><meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"android:value="true" /></activity>

SettingsHomepageActivity.java,主要从onCreate()方法开始:

@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.settings_homepage_container);final View root = findViewById(R.id.settings_homepage_container);root.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);setHomepageContainerPaddingTop();final Toolbar toolbar = findViewById(R.id.search_action_bar);FeatureFactory.getFactory(this).getSearchFeatureProvider().initSearchToolbar(this /* activity */, toolbar, SettingsEnums.SETTINGS_HOMEPAGE);final ImageView avatarView = findViewById(R.id.account_avatar);final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(this, avatarView);getLifecycle().addObserver(avatarViewMixin);if (!getSystemService(ActivityManager.class).isLowRamDevice()) {// Only allow contextual feature on high ram devices.showFragment(new ContextualCardsFragment(), R.id.contextual_cards_content);}showFragment(new TopLevelSettings(), R.id.main_content);((FrameLayout) findViewById(R.id.main_content)).getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
}

可以看到主界面的layout为settings_homepage_container.xml:

<androidx.coordinatorlayout.widget.CoordinatorLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/settings_homepage_container"android:fitsSystemWindows="true"android:layout_width="match_parent"android:layout_height="match_parent"><androidx.core.widget.NestedScrollViewandroid:id="@+id/main_content_scrollable_container"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="com.android.settings.widget.FloatingAppBarScrollingViewBehavior"><LinearLayoutandroid:id="@+id/homepage_container"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:descendantFocusability="blocksDescendants"><FrameLayoutandroid:id="@+id/contextual_cards_content"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginStart="@dimen/contextual_card_side_margin"android:layout_marginEnd="@dimen/contextual_card_side_margin"/><FrameLayoutandroid:id="@+id/main_content"android:layout_width="match_parent"android:layout_height="wrap_content"android:animateLayoutChanges="true"android:background="?android:attr/windowBackground"/></LinearLayout></androidx.core.widget.NestedScrollView><com.google.android.material.appbar.AppBarLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><include layout="@layout/search_bar"/></com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

主界面布局中主要包含三部分:两个FrameLayout,一个顶部快捷搜索栏。其中Id为main_content的FrameLayout就是用来显示主设置内容的,即Settings的一级菜单项界面。.homepage.SettingsHomepageActivity 中的逻辑并不复杂,直接加载了TopLevelSettings这个Fragment。

showFragment(new TopLevelSettings(), R.id.main_content);

TopLevelSettings通过AndroidX的Preference来展示设置项列表,设置项列表的内容通过静态配置+动态添加的方式获取。
后面分开分析:SettingsActivity.java、DashboardFragment.java。

2 SettingsActivity.java

Settings 继承了 SettingsActivity,有着大量的静态类,但其中并没有实现任何逻辑,那它是怎么加载到自己应有的布局的呢?
其实这些Activity的逻辑都是在SettingsActivity中实现。
在父类SettingsActivity的onCreate()中:

    @Override  protected void onCreate(Bundle savedState) {  super.onCreate(savedState);  long startTime = System.currentTimeMillis();  //工厂类实现方法com.android.settings.overlay.FeatureFactoryImpl.java  final FeatureFactory factory = FeatureFactory.getFactory(this);  //获取菜单信息的工厂类,实现类为DashboardFeatureProviderImpl.java  mDashboardFeatureProvider = factory.getDashboardFeatureProvider(this);  mMetricsFeatureProvider = factory.getMetricsFeatureProvider();  // 第一步    从intent信息中获取<meta-data/>标签名为"com.android.settings.FRAGMENT_CLASS"的值(下文用于加载Fragment的类名)  getMetaData();  // 第二步final Intent intent = getIntent();if (intent.hasExtra(EXTRA_UI_OPTIONS)) {getWindow().setUiOptions(intent.getIntExtra(EXTRA_UI_OPTIONS, 0));}//获取上面getMetaData()得到的类名  final String initialFragmentName = intent.getStringExtra(EXTRA_SHOW_FRAGMENT);  //是否为快捷进入方式(如从其它的应用进入Settings的某个设置项)  mIsShortcut = isShortCutIntent(intent) || isLikeShortCutIntent(intent) ||  intent.getBooleanExtra(EXTRA_SHOW_FRAGMENT_AS_SHORTCUT, false);  ... ...  if (savedState != null) {  ... ...  } else {  //  第三步   加载布局  launchSettingFragment(initialFragmentName, isSubSettings, intent);  }  ... ...  }

第一步:
首先通过getMetaData()获取该Activity在manifest中配置的fragment, 并赋值给mFragmentClass。

    private void getMetaData() {try {ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),PackageManager.GET_META_DATA);if (ai == null || ai.metaData == null) return;mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);} catch (NameNotFoundException nnfe) {// No recoveryLog.d(LOG_TAG, "Cannot get Metadata for: " + getComponentName().toString());}}

第二步:
通过getIntent()方法、getStartingFragmentClass()方法筛选出要启动的Fragment。
第三步:
通过launchSettingFragment()启动对应Fragment,这里的initialFragmentName参数就是第二步Intent中包含的EXTRA_SHOW_FRAGMENT参数,mFragmentClass不为空的情况下传入的就是mFragmentClass。

3 DashboardFragment.java

通过上面知道,SettingsHomepageActivity 直接加载了TopLevelSettings这个Fragment。而该Fragment继承了DashboardFragment,先来看TopLevelSettings的构造方法:

    public TopLevelSettings() {final Bundle args = new Bundle();// Disable the search icon because this page uses a full search view in actionbar.args.putBoolean(NEED_SEARCH_ICON_IN_ACTION_BAR, false);setArguments(args);}

可以看到构造方法中仅设置了个标志位,再根据framgments生命周期先来看onAttach()方法:

    @Overridepublic void onAttach(Context context) {super.onAttach(context);use(SupportPreferenceController.class).setActivity(getActivity());}

调用父类DashboardFragment.java的onAttach()方法,此方法主要是完成mPreferenceControllers的加载。
接着看onCreate()方法,因为TopLevelSettings未重写父类的方法,所以直接看父类DashboardFragment的onCreate()方法。

    @Overridepublic void onCreate(Bundle icicle) {super.onCreate(icicle);// Set ComparisonCallback so we get better animation when list changes.getPreferenceManager().setPreferenceComparisonCallback(new PreferenceManager.SimplePreferenceComparisonCallback());if (icicle != null) {// Upon rotation configuration change we need to update preference states before any// editing dialog is recreated (that would happen before onResume is called).updatePreferenceStates();}}

根据log定位发现,其后调用DashboardFragment.java的onCreatePreferences()方法:这里我也不知道怎么调用到这来的,哈哈。

    @Overridepublic void onCreatePreferences(Bundle savedInstanceState, String rootKey) {refreshAllPreferences(getLogTag());}/*** Refresh all preference items, including both static prefs from xml, and dynamic items from* DashboardCategory.*/private void refreshAllPreferences(final String TAG) {final PreferenceScreen screen = getPreferenceScreen();// First remove old preferences.if (screen != null) {// Intentionally do not cache PreferenceScreen because it will be recreated later.screen.removeAll();}// Add resource based tiles.displayResourceTiles();refreshDashboardTiles(TAG);final Activity activity = getActivity();if (activity != null) {Log.d(TAG, "All preferences added, reporting fully drawn");activity.reportFullyDrawn();}updatePreferenceVisibility(mPreferenceControllers);}

以看到此方法主要是用来加载显示的preference items,主要分为两部分,一个是静态xml定义的prefs(调用displayResourceTiles()方法),另一部分是从DashboardCategory动态加载(调用refreshDashboardTiles(TAG)方法,其中TAG为 “TopLevelSettings”)。
displayResourceTiles()
此方法主要是从xml资源文件中加载显示prefs:

    /*** Displays resource based tiles.*/private void displayResourceTiles() {final int resId = getPreferenceScreenResId();if (resId <= 0) {return;}addPreferencesFromResource(resId);final PreferenceScreen screen = getPreferenceScreen();screen.setOnExpandButtonClickListener(this);mPreferenceControllers.values().stream().flatMap(Collection::stream).forEach(controller -> controller.displayPreference(screen));}

首先调用getPreferenceScreenResId()方法获取所要加载的xml的ID:

    @Overrideprotected abstract int getPreferenceScreenResId();

最终回调用到子类TopLevelSettings.java的getPreferenceScreenResId()方法:

    @Overrideprotected int getPreferenceScreenResId() {return R.xml.top_level_settings;}

此主要是调用androidX Preference的addPreferencesFromResource()方法。此方法主要是将preferenceScreen下所有Preference添加到ArrayList中,然后再根据此集合构建生成PreferenceGroupAdapter,最后将此adapter设置到listview中,完成数据绑定,从而完成界面加载。在这里就要明白mPreferenceControllers是什么,在哪初始化的?
我们很快就可以找到:在onAttach()中添加的。

        final List<AbstractPreferenceController> controllers = new ArrayList<>();// Load preference controllers from codefinal List<AbstractPreferenceController> controllersFromCode =createPreferenceControllers(context);// Load preference controllers from xml definitionfinal List<BasePreferenceController> controllersFromXml = PreferenceControllerListHelper.getPreferenceControllersFromXml(context, getPreferenceScreenResId());// Filter xml-based controllers in case a similar controller is created from code already.final List<BasePreferenceController> uniqueControllerFromXml =PreferenceControllerListHelper.filterControllers(controllersFromXml, controllersFromCode);// Add unique controllers to list.if (controllersFromCode != null) {controllers.addAll(controllersFromCode);}controllers.addAll(uniqueControllerFromXml);// And wire up with lifecycle.final Lifecycle lifecycle = getSettingsLifecycle();uniqueControllerFromXml.stream().filter(controller -> controller instanceof LifecycleObserver).forEach(controller -> lifecycle.addObserver((LifecycleObserver) controller));mPlaceholderPreferenceController =new DashboardTilePlaceholderPreferenceController(context);controllers.add(mPlaceholderPreferenceController);for (AbstractPreferenceController controller : controllers) {addPreferenceController(controller);}

可以发现:

  1. 从代码中加载preference controllers,调用createPreferenceControllers()方法;
  2. 从xml定义中加载preference controllers,调用getPreferenceControllersFromXml()方法。
  3. 过滤重复定义的controller等,赋值填充mPreferenceControllers。

再回到displayResourceTiles()方法中的:

mPreferenceControllers.values().stream().flatMap(Collection::stream).forEach(controller -> controller.displayPreference(screen));

此语句主要就是调用各个controller的displayPreference()方法。
以网络和互联网菜单项为例,xml中配置的controller为"com.android.settings.network.TopLevelNetworkEntryPreferenceController",查看TopLevelNetworkEntryPreferenceController.java发现,其内并未实现displayPreference()方法,查看继承关系:是继承BasePreferenceController的,接着查看BasePreferenceController中的displayPreference()方法。

    /*** Displays preference in this controller.*/@Overridepublic void displayPreference(PreferenceScreen screen) {super.displayPreference(screen);if (getAvailabilityStatus() == DISABLED_DEPENDENT_SETTING) {// Disable preference if it depends on another setting.final Preference preference = screen.findPreference(getPreferenceKey());if (preference != null) {preference.setEnabled(false);}}}

又是调用BasePreferenceController父类AbstractPreferenceController中的displayPreference:

    /*** Displays preference in this controller.*/public void displayPreference(PreferenceScreen screen) {final String prefKey = getPreferenceKey();if (TextUtils.isEmpty(prefKey)) {Log.w(TAG, "Skipping displayPreference because key is empty:" + getClass().getName());return;}if (isAvailable()) {setVisible(screen, prefKey, true /* visible */);if (this instanceof Preference.OnPreferenceChangeListener) {final Preference preference = screen.findPreference(prefKey);preference.setOnPreferenceChangeListener((Preference.OnPreferenceChangeListener) this);}} else {setVisible(screen, prefKey, false /* visible */);}}
  1. getPreferenceKey()获取preference的key,会调用到子类BasePreferenceController.java的getPreferenceKey()方法:
    @Overridepublic String getPreferenceKey() {return mPreferenceKey;}

而据上面分析到mPreferenceKey实质上即为xml中每个preference配置的android:key属性的值,即此处应为"top_level_network"。(以网络和互联网菜单项为例)
2. isAvailable();判断此preference是否可用即是否应该被显示。如果返回true,则被显示出来,反之则不被显示,最终也会调用到BasePreferenceController.java的isAvailable()方法:

    @Overridepublic final boolean isAvailable() {final int availabilityStatus = getAvailabilityStatus();return (availabilityStatus == AVAILABLE|| availabilityStatus == AVAILABLE_UNSEARCHABLE|| availabilityStatus == DISABLED_DEPENDENT_SETTING);}

注意:看这里的BasePreferenceController.java中的isAvailable()方法中的getAvailabilityStatus(),一直跟进去,会发现调用的是:BasePreferenceController子类TopLevelNetworkEntryPreferenceController.java的getAvailabilityStatus()方法:

    @Overridepublic int getAvailabilityStatus() {return Utils.isDemoUser(mContext) ? UNSUPPORTED_ON_DEVICE : AVAILABLE_UNSEARCHABLE;}
  1. 调用setVisible()方法设置是否可被显示:setVisible(screen, prefKey, true /* visible */);
    frameworks/base/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java
    protected final void setVisible(PreferenceGroup group, String key, boolean isVisible) {final Preference pref = group.findPreference(key);if (pref != null) {pref.setVisible(isVisible);}}
  1. 判断controller是否实现了Preference.OnPreferenceChangeListener接口,是,则设置监听。
    综上,如果希望preference不被显示在界面上,可以通过实现相关preference的controller的getAvailabilityStatus()方法,使此方法的返回值不为AVAILABLE、AVAILABLE_UNSEARCHABLE、DISABLED_DEPENDENT_SETTING即可。
  2. 继续看查看BasePreferenceController.java的displayPreference()方法的剩余语句:
        if (getAvailabilityStatus() == DISABLED_DEPENDENT_SETTING) {// Disable preference if it depends on another setting.final Preference preference = screen.findPreference(getPreferenceKey());if (preference != null) {preference.setEnabled(false);}}

根据子类controller实现的getAvailabilityStatus()方法的返回值判断是否需要将此preference置为不可点击。
至此,DashboardFragment.java中displayResourceTiles()方法分析完成。

总结:

  1. Settings的主Activity实质实现是在SettingsHomepageActivity.java内;
  2. Settings的主界面设置item的显示是在fragment上,fragment为TopLevelSettings.java,加载显示的布局为top_level_settings.xml;
  3. Settings主界面设置项item的加载显示主要分为两部分,一部分是xml定义的静态加载,xml为top_level_settings.xml;一部分是DashboardCategory来获取动态加载。
  4. 每个设置项item均为一个preference,通过xml定义加载时,必须要有一个controller,可以是在xml中定义"settings:controller"属性声明,名称必须与类的包名路径相同;也可直接在相关fragment中实现createPreferenceControllers()方法去调用构造相关controller。此二者存其一即可。
  5. xml中配置preference时,必须定义”android:key“属性;
  6. 需要隐藏不显示某个设置项时,一是可以直接在xml中注释其定义;二是可以在相关设置项preference的controller类中实现getAvailabilityStatus()方法,使此方法的返回值不为AVAILABLE、AVAILABLE_UNSEARCHABLE、DISABLED_DEPENDENT_SETTING即可;
  7. 如果需要某个设置项不可点击,一是可以直接调用setEnabled()。二是可以在相关设置项preference的controller类中实现getAvailabilityStatus()方法,使此方法的返回值为DISABLED_DEPENDENT_SETTING即可。

相关文章:

Android 10.0 Settings 加载流程

一、系统设置首页 代码路径&#xff1a;packages/app/Settings/ 1 主界面加载&#xff1a; <!-- Alias for launcher activity only, as this belongs to each profile. --><activity-alias android:name"Settings"android:label"string/settings_la…...

mysql的索引、事务和存储引擎

目录 索引 索引的概念 索引的作用 作用 索引的副作用 创建索引 创建索引的原则和依据 索引的类型 创建索引 查看索引 删除索引 drop 主键索引 普通索引 添加普通索引 唯一索引 添加唯一索引 组合索引 添加组合索引 查询组合索引 全文索引 添加全文索引 …...

基于trace_id实现SpringCloudGateway网关的链路追踪

之前写的两篇关于基于 trace_id 的链路追踪的文章&#xff1a; 基于trace_id的链路追踪&#xff08;含Feign、Hystrix、线程池等场景&#xff09;基于trace_id的链路追踪&#xff08;ForkJoinPool场景&#xff09; 一、引言 在之前的文章中&#xff0c;我们讨论了基于 trace…...

Windows 11 version 22H2 中文版、英文版 (x64、ARM64) 下载 (updated Jul 2024)

Windows 11 version 22H2 中文版、英文版 (x64、ARM64) 下载 (updated Jul 2024) Windows 11, version 22H2&#xff0c;企业版 arm64 x64 请访问原文链接&#xff1a;https://sysin.org/blog/windows-11/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者…...

【C语言】动态内存管理(上)

文章目录 前言1.为什么要存在动态内存2. malloc和free2.1 malloc2.2 free2.3 使用实例&#xff08;malloc和free&#xff09; 3. calloc3.1 calloc例子 前言 本文开始将开始学习C语言中一个比较重要的知识点或者是操作——动态内存管理。由于本次的知识比较重要&#xff0c;为…...

【BUG】已解决:ModuleNotFoundError: No module named‘ pip‘

已解决&#xff1a;ModuleNotFoundError: No module named‘ pip‘ 目录 已解决&#xff1a;ModuleNotFoundError: No module named‘ pip‘ 【常见模块错误】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰…...

网络安全-网络安全及其防护措施11

51.网络容量规划 网络容量规划的概念和重要性 网络容量规划&#xff1a; 是指根据业务需求和预期增长&#xff0c;合理规划和设计网络的带宽、设备和资源&#xff0c;以满足未来网络流量和服务质量的需求。通过有效的网络容量规划&#xff0c;确保网络性能稳定和用户体验良好…...

使用IDEA编写lua脚本并运行

下载lua https://github.com/rjpcomputing/luaforwindows/releases 是否创建桌面快捷方式&#xff1a;我们的目标是使用IDEA编写lua脚本&#xff0c;所以不需要勾选。后面需要的话&#xff0c;可以到安装目录下手动创建快捷方式 环境变量自动配置 安装后会自动配置好环境变量…...

CentOS 7 安装MySQL 5.7.30

CentOS 7 安装MySQL卸载&#xff08;离线安装&#xff09; 安装配置MySQL之前先查询是否存在&#xff0c;如存在先卸载再安装 rpm -qa|grep -i mysql rpm -qa|grep -i mariadb rpm -e --nodeps mariadb-libs-5.5.68-1.el7.x86_64如下命令找到直接 rm -rf 删除&#xff08;删除…...

Bash 学习摘录

文章目录 1、变量和参数的介绍&#xff08;1&#xff09;变量替换$(...) &#xff08;2&#xff09;特殊的变量类型export位置参数shift 2、引用&#xff08;1&#xff09;引用变量&#xff08;2&#xff09;转义 3、条件判断&#xff08;1&#xff09;条件测试结构&#xff08…...

GD32 MCU是如何进入中断函数的

用过GD32 MCU的小伙伴们都知道&#xff0c;程序是顺序执行的&#xff0c;但当有中断来的时候程序会跳转到中断函数&#xff0c;执行完中断函数后程序又继续回到原来的位置继续执行&#xff0c;那么你们知道MCU是如何找到中断函数入口的吗&#xff1f; 今天我们就以GD32F303系列…...

Ruby 循环

Ruby 循环 在编程中&#xff0c;循环是一种常用的控制结构&#xff0c;它允许我们重复执行一段代码多次。Ruby 作为一种灵活的编程语言&#xff0c;提供了多种循环方法&#xff0c;包括 while、until、for、each 和 loop 等。本文将详细介绍 Ruby 中的循环机制&#xff0c;并通…...

三字棋游戏(C语言详细解释)

hello&#xff0c;小伙伴们大家好&#xff0c;算是失踪人口回归了哈&#xff0c;主要原因是期末考试完学校组织实训&#xff0c;做了俄罗斯方块&#xff0c;后续也会更新&#xff0c;不过今天先从简单的三字棋说起 话不多说&#xff0c;开始今天的内容 一、大体思路 我们都知…...

H3CNE(计算机网络的概述)

1. 计算机网络的概述 1.1 计算机网络的三大基本功能 1. 资源共享 2. 分布式处理与负载均衡 3. 综合信息服务 1.2 计算机网络的三大基本类型 1.3 网络拓扑 定义&#xff1a; 网络设备连接排列的方式 网络拓扑的类型&#xff1a; 总线型拓扑&#xff1a; 所有的设备共享一…...

【极客日常】Golang一个的slice数据替换的bug排查

上周某天下班前&#xff0c;接到同事转来一个bug要排查&#xff0c;症状是代码重构之后某些业务效果不符合预期&#xff0c;由于代码重构人是笔者&#xff0c;于是blame到笔者这边。经过10min左右的排查和尝试后&#xff0c;解决了这个问题&#xff1a;既往逻辑没有改动&#x…...

HarmonyOS应用开发者高级认证,Next版本发布后最新题库 - 单选题序号3

基础认证题库请移步&#xff1a;HarmonyOS应用开发者基础认证题库 注&#xff1a;有读者反馈&#xff0c;题库的代码块比较多&#xff0c;打开文章时会卡死。所以笔者将题库拆分&#xff0c;单选题20个为一组&#xff0c;多选题10个为一组&#xff0c;题库目录如下&#xff0c;…...

UE4-光照重建

当我们拉入新的光源和模型到我们的场景中后&#xff0c;会产生这样的情况&#xff1a; Preview:预览 表示此时由于光照物体所产生的阴影都是预览级别的并不是真正的效果。 方法一&#xff1a; 或者也可以在世界大纲中选中我们的光源&#xff0c;然后将我们的光源改变为可以…...

【2024德国签证】留学面签问题汇总

在去交材料的时候&#xff0c;可能会被随机安排面试。这些面试问题一般都很简单&#xff0c;主要是测试你的基本英文交流能力。无需担心&#xff0c;签证官不会问太专业的问题&#xff0c;因为他们也不懂专业内容。到目前为止&#xff0c;没有一个博士生因为这个面试被拒签。毕…...

知识点大纲

学习方法 学习、整理笔记过程中&#xff0c;顺便整理出一个以问题为模版的大纲&#xff0c;到时候对着问题&#xff0c;就像是在和面试官讲解那样&#xff0c;相当于升级版的费曼学习法 除了看博客&#xff0c;问gpt外&#xff0c;亲自实验也是获取知识及加深印象的关键点 很…...

MySQL:库表操作

MySQL&#xff1a;库表操作 库操作查看创建字符编码集 删除修改备份 表操作创建查看删除修改 库操作 查看 查看存在哪些数据库&#xff1a; show databases;示例&#xff1a; 查看自己当前处于哪一个数据库&#xff1a; select database();示例&#xff1a; 此处由于我不处于任…...

8.3 End-to-end Data Protection (Optional)

8.3 End-to-end Data Protection (Optional) 为了提供从应用程序到NVM介质并返回到应用程序本身的稳健数据保护,可以使用端到端数据保护。如果启用了此可选机制,则将额外的保护信息(例如CRC)添加到逻辑块中,控制器和/或主机软件可以对其进行评估,以确定逻辑块的完整性。…...

python实现图像对比度增强算法

python实现直方图均衡化、自适应直方图均衡化、连接组件标记算法 1.直方图均衡化算法详解算法步骤公式Python 实现详细解释优缺点 2.自适应直方图均衡化算法详解算法步骤公式Python 实现详细解释优缺点 3.连接组件标记算法详解算法步骤8连通与4连通公式Python 实现详细解释优缺…...

【D3.js in Action 3 精译_020】2.6 用 D3 设置与修改元素样式 + 名人专访(Nadieh Bremer)+ 2.7 本章小结

当前内容所在位置 第一部分 D3.js 基础知识 第一章 D3.js 简介&#xff08;已完结&#xff09; 1.1 何为 D3.js&#xff1f;1.2 D3 生态系统——入门须知1.3 数据可视化最佳实践&#xff08;上&#xff09;1.3 数据可视化最佳实践&#xff08;下&#xff09;1.4 本章小结 第二章…...

GIT命令学习 二

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 ☁️运维工程师的职责&#xff1a;监…...

LeetCode 150, 112, 130

文章目录 150. 逆波兰表达式求值题目链接标签思路代码 112. 路径总和题目链接标签思路代码 130. 被围绕的区域题目链接标签思路代码 150. 逆波兰表达式求值 题目链接 150. 逆波兰表达式求值 标签 栈 数组 数学 思路 本题很像 JVM 中的 操作数栈&#xff0c;当写出以下三行…...

c++应用网络编程之五Windows常用的网络IO模型

一、Windows的网络编程 其实对开发者而言&#xff0c;只有Windows和其它平台。做为一种普遍流行的图形OS&#xff0c;其一定会与类Linux的编程有着明显的区别&#xff0c;这点当然也会体现在网络编程上。Windows有着自己一套相对独立的上层Socket编程模型或者说框架&#xff0…...

PostgreSQL 中如何解决因大量并发删除和插入操作导致的索引抖动?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 PostgreSQL 中如何解决因大量并发删除和插入操作导致的索引抖动一、理解索引抖动二、索引抖动的影响三…...

鑫创SSS1700USB音频桥芯片USB转IIS芯片

鑫创SSS1700支持IIC初始外部编&#xff08;EEPROM选项),两线串行总线&#xff08;I2C总线&#xff09;用于外部MCU控制整个EEPROM空间可以通过MCU访问用于主机控制同步的USB HID外部串行EEPROM&#xff08;24C02~24C16&#xff09;接口&#xff0c;用于客户特定的USB视频、PID、…...

计算机视觉发展历程

文章目录 前言一、发展历程1&#xff09;、萌芽期&#xff08;1960s-1970s&#xff09;2&#xff09;、基础发展期&#xff08;1980s&#xff09;3&#xff09;、系统开发期&#xff08;1990s-2000s&#xff09;4&#xff09;、深度学习兴起期&#xff08;2010s&#xff09;5&a…...

从安装Node到TypeScript到VsCode的配置教程

从安装Node到TypeScript到VsCode的配置教程 1.下载Node安装包&#xff0c; 链接 2.双击安装包&#xff0c;选择安装路径&#xff0c;如下&#xff1a; 3.一直点击下一步&#xff0c;直至安装结束即可&#xff1a; 这个时候&#xff0c;node会默认配置好环境变量&#xff0c;并且…...

福建建设银行网站/亚马逊seo推广

第一步&#xff1a;打开下面网址.https://mcp.microsoft.com/authenticate/validatemcp.aspx第二步&#xff1a;在出现在页面中输入相对应Code后&#xff0c;点击Submit即可Transcript ID : 945443Access Code : SR6975175转载于:https://blog.51cto.com/76287/760132...

北京怎么样做网站/网络营销的有哪些特点

集合&#xff1a;&#xff08;同数学概念&#xff09; 多个元素的无序组合 - 用{} 表示&#xff0c;元素间用逗号分隔 - 元素类型不必相同 - 每个元素唯一&#xff0c;不存在相同元素 - 元素不可更改&#xff0c;不能是可变数据类型 创建集合类型&#xff1a; {} 或 set()&…...

wordpress 离线更新/人民网 疫情

网友 oneway_01 问了我一个问题&#xff0c;对于工作流形业务建模提出了一些疑问。这是好问题&#xff0c;值得讨论&#xff0c;特意将它发表出来。另一方面&#xff0c;能够做出这样的思考&#xff0c;说明oneway_01同学对用例方法的认知已经很深入了。恭喜一下&#xff01;**…...

衡水做wap网站/汕头seo排名收费

1. 概述 艿艿信奉的话很多&#xff0c;其中很重要的一条&#xff1a;在考虑高性能之前&#xff0c;一定要做高可用。很多时候&#xff0c;我们常常陷入追求一个功能或者系统的高性能&#xff0c;却忽略了高可用。 为什么在这篇文章的开头提到这个段呢&#xff1f;对于任何系统…...

深圳网站建设公司元/电商网页制作教程

一、关于javabean javabean是固定写法的java类 书写格式为&#xff1a; 1)必须有无参构造函数 2)属性必须私有&#xff0c; 我们称为字段 3)提供标准的getter和setter 例&#xff1a; name 字段 的getter: String getName() settter: void setName(String name) javabean例子&a…...

做jsp网站用哪些软件下载/我想做网络推广

系统引导过程:1.POST(Power On Self Test) 硬件自检2.读取MBR(bootloader&#xff1a;446字节 磁盘分区:64字节 分区标志位:2字节(55AA))通过读取MBR中的将bootloader加载至内存&#xff0c;而该bootloader的程序通常就是Grub&#xff0c;Grub主要的功能加载系统内核(进入操作系…...