Android 10.0 Settings source code analysis of the main interface loading (3)

The first two articles respectively record the main interface of Settings,
static xml loading settings, the main interface loading of Android 10.0 Settings source code analysis (1)
Dynamic loading of settings from AndroidManifest.xml, the main interface loading of Android 10.0 Settings source code analysis (2)
This article is mainly After the record setting item is loaded, the interface displays the update process.

Let's continue with the analysis of the first two articles first, and look at the logic behind the refreshAllPreferences() method:
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);

When all the preferences are loaded, notify the activity to redraw and display; call the updatePreferenceVisibility() method:

    @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());
                }
            }
        }
    }

You can see that you need to satisfy that screen, preferenceControllers, and mBlockerController are not null in order to perform subsequent operations. The follow-up is mainly to traverse the controller collection mPreferenceControllers of all preference setting items on the interface, and set whether it can be displayed on the interface;
the initialization of mBlockerController:
DashboardFragment.java#onAttach() method:

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));
        }
    }

Filter whether there is a controller element that implements the BasePreferenceController.UiBlocker interface in the controller collection mPreferenceControllers of all preference setting items on this interface, and add it to the keys collection. Currently, the main interface of Settings has not been implemented, so this set is null, that is, mBlockerController is also null.

That is, the updatePreferenceVisibility() method is temporarily not executed when the main interface is loaded.
So far the refreshAllPreferences() method analysis is complete.

onStart()

Let's look at the other life cycle methods of the main interface TopLevelSettings.java. Since it does not implement the onStart() and onResume() life cycle methods, look directly at the onStart() method of the parent class DashboardFragment.java:

    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);
        }
    }

Get whether there is a DashboardCategory object that can be dynamically displayed on the current interface; call the setListening method to "monitor", determine whether the activity in which the current fragment is located is inherited from SettingsBaseActivity, and decide whether to set CategoryListener to monitor.

onResume ()

The life cycle of fragment onResume() method:

    @Override
    public void onResume() {
    
    
        super.onResume();
        updatePreferenceStates();
    }

Call the updatePreferenceStates() method, and each controller manages and updates the corresponding preference items according to its own needs:

    /**
     * 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);
            }
        }
    }

Traverse the mPreferenceControllers collection to determine whether the corresponding preference is available and displayable for each controller element in the collection; whether the corresponding preference defines the key attribute. Then according to the obtained key, get the corresponding preference on the interface, and then call the updateState() method to update the preference state.

updateState()

If the relevant controller implements the updateState() method internally, the updateState() method of its own method is called;

If not defined, call the updateState() method of its parent class:
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);
    }

The refreshSummary() method is called. Similarly, if the relevant controller implements the refreshSummary() method by itself, the refreshSummary() method implemented by itself is called;
if it is not defined, the refreshSummary() method in AbstractPreferenceController.java is called:

    /**
     * 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);
    }

Call the getSummary() method, the rules are the same as above, get the summary string that needs to be displayed and set it to preference.

So far the main interface setting item loading process is recorded.

Guess you like

Origin blog.csdn.net/Otaku_627/article/details/108843487