Settings源码分析1

settings源码路径:packages/app/Settings/

一、settings设置首页

Settings 模块中的 AndroidManifest.xml 文件

<activity android:name=".homepage.SettingsHomepageActivity"
  android:label="@string/settings_label_launcher"
  android:theme="@style/Theme.Settings.Home"
  android:taskAffinity="com.android.settings.root"
  android:launchMode="singleTask"
  android:configChanges="keyboard|keyboardHidden">
  <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>
.....
<!-- Alias for launcher activity only, as this belongs to each profile. -->
<activity-alias android:name="Settings"
  android:label="@string/settings_label_launcher"
  android:taskAffinity="com.android.settings.root"
  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的主界面是com.android.settings.Settings,但它是一个activity-alias,指向的是.homepage.SettingsHomepageActivity
activity-alias可用来设置某个Activity的快捷入口,可以放在桌面上或者通过该别名被其他组件快速调起。 android:targetActivity为目标Activity.
从SettingsHomepageActivity.java中可以看出,onCreate()方法加载的layout是settings_homepage_container.xml
在onCreate()方法中调用了showFragment(new TopLevelSettings(), R.id.main_content);
可以看到一级菜单启动的是TopLevelSettings,TopLevelSettings继承于DashboardFragment.java。
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);
}

可以看到通过构造方法传递了一个参数,从注释中可以看出,该参数的用意是由于主界面使用完整的搜索视图所以在主界面的actionbar中隐藏了搜索图标。然后再根据framgments生命周期先来看onAttach()方法:

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

调用了父类的onAttach()方法,完成preference controllers的加载,DashboardFragment.java的onCreate()方法:

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        //设置ComparisonCallback,以便在列表更改时获得更好的动画效果。
        getPreferenceManager().setPreferenceComparisonCallback(
                new PreferenceManager.SimplePreferenceComparisonCallback());
        if (icicle != null) {
 //在旋转配置更改后,我们需要在执行任何操作之前更新首选项状态
//重新创建编辑对话框(这将在调用onResume之前发生)。
            updatePreferenceStates();
        }
}

设置ComparisonCallback,以便在列表更改时获得更好的动画效果。
第一次进入时,icicle为null,其后调用Dashboardfragment.java的onCreatePreferences()方法:

public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        checkUiBlocker(mControllers);
        refreshAllPreferences(getLogTag());
        mControllers.stream()
        .map(controller -> (Preference) findPreference(controller.getPreferenceKey()))
         .filter(Objects::nonNull)
            .forEach(preference -> {
                   //给所有控制器一个处理点击的机会。
                    preference.getExtras().putInt(CATEGORY, getMetricsCategory());
         });
    }

调用refreshAllPreferences():

  // 刷新所有首选项,包括来自xml的静态首选项和来自DashboardCategory的动态项。
    private void refreshAllPreferences(final String tag) {
        final PreferenceScreen screen = getPreferenceScreen();
      //首先删除旧的首选项。
        if (screen != null) {
            //有意不要缓存PreferenceScreen,因为它将在稍后重新创建。
            screen.removeAll();
        }
       //添加基于资源的互动程序。
        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的静态preference和来自DashboardCategory的动态preference,静态xml定义的prefs(调用displayResourceTiles()方法),动态DashboardCategory动态加载(调用refreshDashboardTiles(TAG)方法,其中TAG为 “TopLevelSettings”)。

二、静态加载

首先调用getpreferenceScreenResId()方法获取所要加载的xml的id,然后调用子类TopLevelSettings.java的getPerferenceScreenResId()方法,返回主界面top_level-settings,因此settings的主界面加载的是top_level_settings。
主界面主要是一些preference菜单项,如网络、通知、电池、应用等等,Preference的配置含义:

  • key:唯一性id;
  • title:标题;
  • summary:简介;
  • ico:图标;
  • order:加载显示优先级,order为负数时,绝对值越高

总结

  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中实现createPreferenceController()方法去调用构造相关controller。此二者存一即可。
  5. xml中配置preference时,必须定义“android;key”属性。

如果我的文章对您有帮助,还请您多多支持我。支付宝帮忙扫一下吧
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pengkai火火火

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值