Settings菜单加载
第三方加载,例如google、健康加载都是第三方,他们是读取的该类的配置文件。
<meta-data
android:name="com.android.settings.category" android:value="com.android.settings.category.ia.homepage" />
<meta-data
android:name="com.android.settings.keyhint"
android:value="top_level_google" />
<activity-alias
android:theme="@ref/0x7f160ddb"
android:label="@ref/0x7f1c0051"
android:icon="@ref/0x7f0803a1" android:name="com.google.android.gms.app.settings.GoogleSettingsIALink" android:exported="true" android:process="@ref/0x7f15056c" android:taskAffinity="com.google.android.gms.common.settings"
android:targetActivity="com.google.android.gms.app.settings.GoogleSettingsActivity">
可以访问到,可以调用,但是为什么在我们的手机中我们不能把它进行卸载,它肯定是采用了系统签名,我们才不能去卸载,并且android:exported=true,这样它可以访问到这个app中的所有数据.
DashboardFragment.refreshAllPreferences
看剩余的方法(refreshAllPreference)
final Activity activity = getActivity();
if (activity != null) {
Log.d(TAG, "All preferences added, reporting fully drawn");
activity.reportFullyDrawn();
}
updatePreferenceVisibility(mPreferenceControllers);
当所有的preference加载完成后,就去通知activity进行重绘显示;就去调用updatePreferenceVisibility
@VisibleForTesting
void updatePreferenceVisibility(
Map<Class, List<AbstractPreferenceController>> preferenceControllers) {
final PreferenceScreen screen = getPreferenceScreen();
if (screen == null || preferenceControllers == null || mBlockerController == null) {
return;
}
final boolean visible = mBlockerController.isBlockerFinished();
for (List<AbstractPreferenceController> controllerList :
preferenceControllers.values()) {
for (AbstractPreferenceController controller : controllerList) {
final String key = controller.getPreferenceKey();
final Preference preference = findPreference(key);
if (preference != null) {
preference.setVisible(visible && controller.isAvailable());
}
}
}
}
可以看到需要满足screen、preferenceControllers、mBlockerController都不为null,才能执行后续操作。后续主要是遍历该界面所有preference设置项的controller集合mPreferenceControllers,设置是否可显示在界面上;
mBlockerController的初始化:
DashboardFragment.java#onAttach()方法
DashboardFragment.onCreatePreferences
@Overridepublic void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
checkUiBlocker(mControllers);
refreshAllPreferences(getLogTag());
mControllers.stream()
.map(controller -> (Preference)
findPreference(controller.getPreferenceKey()))
.filter(Objects::nonNull)
.forEach(preference -> {
// Give all controllers a chance to handle click.
/**
* 给所有控制器一个处理点击的机会。
*/
preference.getExtras().putInt(CATEGORY, getMetricsCategory());
});}
再次进入checkUiBlocker(mControllers)
@VisibleForTesting
void checkUiBlocker(List<AbstractPreferenceController> controllers) {
final List<String> keys = new ArrayList<>();
controllers
.stream()
.filter(controller -> controller instanceof BasePreferenceController.UiBlocker)
.forEach(controller -> {
((BasePreferenceController) controller).setUiBlockListener(this);
keys.add(controller.getPreferenceKey());
});
if (!keys.isEmpty()) {
mBlockerController = new UiBlockerController(keys);
mBlockerController.start(()->updatePreferenceVisibility(mPreferenceControllers));
}
}
这个可以过滤该界面所有preference设置项的controller集合mPreferenceControllers内是否存在实现了BasePreferenceController.UiBlocker接口的controller元素,添加到keys集合内。目前Settings主界面未有实现,故此集合为null,即mBlockerController也为null。
即updatePreferenceVisibility()方法在主界面加载时暂不执行。
至此refreshAllPreferences()方法分析完成。
onStart()
开始去看生命周期选项,主界面中的TopLevelSettings.java的其他生命周期方法,由于其未实现onStart() 、onResume()生命周期方法,直接看父类DashboardFragment.java的onStart()方法:
@Overridepublic void onStart() {
super.onStart();
final DashboardCategory category = mDashboardFeatureProvider.getTilesForCategory(getCategoryKey());
if (category != null) {
return; }
final Activity activity = getActivity();
if (activity instanceof SettingsBaseActivity) {
mListeningToCategoryChange = true;
((SettingsBaseActivity) activity).addCategoryListener(this); }
final ContentResolver resolver = getContentResolver(); mDashboardTilePrefKeys.values().stream()
.filter(Objects::nonNull)
.flatMap(List::stream)
.forEach(observer -> {
if (!mRegisteredObservers.contains(observer)) {
registerDynamicDataObserver(resolver, observer);
}
});}
获取当前界面是否存在可以动态显示的DashboardCategory对象;判断当前fragment所在的activity是否继承至SettingsBaseActivity,决定是否设置CategoryListener监听。
onResume()
@Overridepublic void onResume() {
super.onResume();
updatePreferenceStates(); writeElapsedTimeMetric(SettingsEnums.ACTION_DASHBOARD_VISIBLE_TIME, "isParalleledControllers:" + isParalleledControllers());}
fragment的生命周期方法onResume方法
调用了updatePreferences方法,每个controller根据自身需要去管理更新对应preference项:
/**
* Update state of each preference managed by PreferenceController.
*/
protected void updatePreferenceStates() {
final PreferenceScreen screen = getPreferenceScreen();
Collection<List<AbstractPreferenceController>> controllerLists =
mPreferenceControllers.values();
for (List<AbstractPreferenceController> controllerList : controllerLists) {
for (AbstractPreferenceController controller : controllerList) {
if (!controller.isAvailable()) {
continue;
}
final String key = controller.getPreferenceKey();
if (TextUtils.isEmpty(key)) {
Log.d(TAG, String.format("Preference key is %s in Controller %s",
key, controller.getClass().getSimpleName()));
continue;
}
final Preference preference = screen.findPreference(key);
if (preference == null) {
Log.d(TAG, String.format("Cannot find preference with key %s in Controller %s",
key, controller.getClass().getSimpleName()));
continue;
}
controller.updateState(preference);
}
}
}
遍历mPreferenceControllers集合判断集合内每个controller元素,对应的preference是否可用可显示;对应的preference是否定义了key属性。再根据获取到的key,获取界面上对应的preference,再调用updateState()方法去更新preference状态。
updateState()
如果相关controller内部自己实现了updateState()方法,则调用其自身方法的updateState()方法;
如果未定义则调用其父类updateState()方法:
frameworks/base/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java
/**
* Updates the current status of preference (summary, switch state, etc)
*/
public void updateState(Preference preference) {
refreshSummary(preference);
}
调用refreshSummary()方法,同样的如果相关controller内部自己实现了refreshSummary()方法,则调用自身实现的refreshSummary()方法;
如果未定义则调用AbstractPreferenceController.java内部的refreshSummary()方法:
/**
* Refresh preference summary with getSummary()
*/
protected void refreshSummary(Preference preference) {
if (preference == null) {
return;
}
final CharSequence summary = getSummary();
if (summary == null) {
// Default getSummary returns null. If subclass didn't override this, there is nothing
// we need to do.
return;
}
preference.setSummary(summary);
}
调用getSummary()方法,规则同上,获取需要显示的summary字串并设置给preference。
至此主界面设置项加载流程记录完