前两篇分别记录了Settings主界面
静态xml加载设置项Android 10.0 Settings源码分析之主界面加载(一)
动态从AndroidManifest.xml中加载设置项Android 10.0 Settings源码分析之主界面加载(二)
本篇主要记录设置项加载完成后,界面显示更新流程。
先来继续接着前两篇分析,来看refreshAllPreferences()方法后面逻辑:
packages/apps/Settings/src/com/android/settings/dashboard/DashboardFragment.java
refreshAllPreferences():
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()方法:
checkUiBlocker(controllers);
@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);
Log.d("zcl"," checkUiBlocker addkey = " + controller.getPreferenceKey());
keys.add(controller.getPreferenceKey());
});
Log.d("zcl"," checkUiBlocker size = " + keys.size());
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()方法:
public void onStart() {
super.onStart();
final DashboardCategory category =
mDashboardFeatureProvider.getTilesForCategory(getCategoryKey());
if (category == null) {
return;
}
if (mSummaryLoader != null) {
// SummaryLoader can be null when there is no dynamic tiles.
mSummaryLoader.setListening(true);
}
final Activity activity = getActivity();
if (activity instanceof SettingsBaseActivity) {
mListeningToCategoryChange = true;
((SettingsBaseActivity) activity).addCategoryListener(this);
}
}
获取当前界面是否存在可以动态显示的DashboardCategory对象;调用setListening方法进行“监听”,判断当前fragment所在的activity是否继承至SettingsBaseActivity,决定是否设置CategoryListener监听。
onResume()
fragment的生命周期onResume()方法:
@Override
public void onResume() {
super.onResume();
updatePreferenceStates();
}
调用updatePreferenceStates()方法,每个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。
至此主界面设置项加载流程记录完毕。