我们知道在Settings中,各模块的Fragment基本都继承了DashboardFragment,当有点击事件时,就会回调DashboardFragment中的onPreferenceTreeClick()方法:
@Override
public boolean onPreferenceTreeClick(Preference preference) {
final Collection<List<AbstractPreferenceController>> controllers =
mPreferenceControllers.values();
for (List<AbstractPreferenceController> controllerList : controllers) {
for (AbstractPreferenceController controller : controllerList) {
if (controller.handlePreferenceTreeClick(preference)) {
// log here since calling super.onPreferenceTreeClick will be skipped
writePreferenceClickMetric(preference);
return true;
}
}
}
return super.onPreferenceTreeClick(preference);
}
在onPreferenceTreeClick()方法中可以根据preference的key做事件拦截,如果不会拦截,将会调用到父类InstrumentedPreferenceFragment的onPreferenceTreeClick()方法:
@Override
public boolean onPreferenceTreeClick(Preference preference) {
writePreferenceClickMetric(preference);
return super.onPreferenceTreeClick(preference);
}
在该方法中,又将会调用到androidx中的PreferenceFragmentCompat方法中,由于androidx中源码不开放,就不做分析,但下一步回将调到SettingsActivity中的onPreferenceStartFragment()方法:
@Override
public boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref) {
new SubSettingLauncher(this)
.setDestination(pref.getFragment())
.setArguments(pref.getExtras())
.setSourceMetricsCategory(caller instanceof Instrumentable
? ((Instrumentable) caller).getMetricsCategory()
: Instrumentable.METRICS_CATEGORY_UNKNOWN)
.setTitleRes(-1)
.launch();
return true;
}
在该方法中由SubSettingLauncher类里面的launch()方法,启动了对应的空Activity,但在Setting中各模块的Activity都时继承SettingsActivity的。但对应的空Activity启动时,就会回执行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);
}
... ...
}
最终在 launchSettingFragment(initialFragmentName, isSubSettings, intent) 方法中加载相对应的Fragment布局,(若注释这句话:你会发现 Activity 启动了,却没有布局)。