Settings菜单加载

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。

至此主界面设置项加载流程记录完

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值