持续创造,加快成长!这是我参加「日新计划 10 月更文挑战」的第27天,点击查看活动概况

接下来会对Preference Library官方库进行一个系列讲解,本篇文章是Preference Library系列的终究一篇,主要是介绍Preference Library中从xml配置设置项到烘托到界面上的整个流程。

xml烘托到界面的流程

xml烘托到屏幕上,便是在PreferenceFragmentCompat的办法onCreatePreferences()中调用了setPreferencesFromResource()完成的:

class SettingsFragment : PreferenceFragmentCompat() {
    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        setPreferencesFromResource(R.xml.settings, rootKey)
    }   
}

所以这儿咱们直接从setPreferencesFromResource()开端剖析。

public void setPreferencesFromResource(@XmlRes int preferencesResId, @Nullable String key) {
    //1.
    requirePreferenceManager();
    //2.
    final PreferenceScreen xmlRoot = mPreferenceManager.inflateFromResource(requireContext(),
            preferencesResId, null);
    final Preference root;
    if (key != null) {
        //3.
        root = xmlRoot.findPreference(key);
        if (!(root instanceof PreferenceScreen)) {
            throw new IllegalArgumentException("Preference object with key " + key
                    + " is not a PreferenceScreen");
        }
    } else {
        root = xmlRoot;
    }
    //4.
    setPreferenceScreen((PreferenceScreen) root);
}
  1. requirePreferenceManager()用来校验下面运用的mPreferenceManager是否为null,是就抛出异常;

  2. inflateFromResource()真实触发xml的解析加载,咱们详细剖析下:

public PreferenceScreen inflateFromResource(@NonNull Context context, int resId,
        @Nullable PreferenceScreen rootPreferences) {
    //...
    final PreferenceInflater inflater = new PreferenceInflater(context, this);
    rootPreferences = (PreferenceScreen) inflater.inflate(resId, rootPreferences);
    //...
    return rootPreferences;
}

要害便是调用了办法PreferenceInflater.inflate(),咱们走进去瞧一瞧 :

完结篇:设置界面的开发利器Preference Library,xml到界面大总结~

首要是经过xml资源id拿到了解析类XmlResourceParser目标,接着持续调用办法inflate()

public Preference inflate(XmlPullParser parser, @Nullable PreferenceGroup root) {
    synchronized (mConstructorArgs) {
        final Preference result;
        try {
            Preference xmlRoot = createItemFromTag(parser.getName(),
                    attrs);
            result = onMergeRoots(root, (PreferenceGroup) xmlRoot);
            rInflate(parser, result, attrs);
        } 
        return result;
    }
}

上面是精简后的代码,能够看到和咱们在Activity中解析布局xml的逻辑基本上都是相同的:

  • 凭借createItemFromTag()获取设置项的标签,并反射加载获取,终究的完成逻辑在createItem()办法中:
private Preference createItem(@NonNull String name, @Nullable String[] prefixes,
        AttributeSet attrs)
        throws ClassNotFoundException, InflateException {
    Constructor<?> constructor = CONSTRUCTOR_MAP.get(name);
    try {
        if (constructor == null) {
            final ClassLoader classLoader = mContext.getClassLoader();
            Class<?> clazz = Class.forName(name, false, classLoader);
            //...
            constructor = clazz.getConstructor(CONSTRUCTOR_SIGNATURE);
            constructor.setAccessible(true);
            CONSTRUCTOR_MAP.put(name, constructor);
        }
        Object[] args = mConstructorArgs;
        args[1] = attrs;
        return (Preference) constructor.newInstance(args);
    } 
}

先尝试从目标池CONSTRUCTOR_MAP中获取当时标签对应类的结构器,假如存在直接调用newInstance()办法反射创立一个Preference目标;

假如缓存池中不存在标签类的结构器,那就经过Class.forName()办法创立标签类的结构器,紧接着加入到缓存CONSTRUCTOR_MAP中,终究和上面一样调用newInstance()创立目标。

  • rInflate()递归解析创立Preference
完结篇:设置界面的开发利器Preference Library,xml到界面大总结~

首要判别是否为intent类型标签和extra标签 ,假如是就先进行特别处理;否则就会调用咱们前面的办法createItemFromTag()创立该节点标签对应的Preference目标,终究持续调用rInflate()递归解析创立Preference

  1. 调用办法findPreference()寻找Preference的根节点,其中查询的key是经过外部进行传的xml根节点的key值;

  2. setPreferenceScreen()真实开端设置RecyclerView的适配器以及数据源,将上面解析的Preference数据烘托到界面中:

完结篇:设置界面的开发利器Preference Library,xml到界面大总结~

postBindPrefeneces()办法会经过Handler发送一条消息,完成数据填充、改写:

完结篇:设置界面的开发利器Preference Library,xml到界面大总结~
完结篇:设置界面的开发利器Preference Library,xml到界面大总结~
完结篇:设置界面的开发利器Preference Library,xml到界面大总结~

getListView()返回的便是一个RecyclerView目标,在这儿设置了其适配器以及对应数据源,终究完成了xml中的数据烘托到界面上 ,完毕 。

总结

Preference Library系列相关的文章到这儿就更新完毕了,总共写了大约十二篇文章,详细的叙述了其运用到原理剖析,其实都不太难,仔细看都能看的懂,希望本篇文章能给你带来协助!!

历史文章

合体篇:设置界面的开发利器Preference Library,源码浅析一下

渡劫篇:设置界面的开发利器Preference Library,接触事件浅析走起~

大乘篇:设置界面的开发利器Preference Library,设置项改写机制浅析~

飞升前篇:设置界面的开发利器Preference Library,多布局设置项完成浅析~

飞升后篇:设置界面的开发利器Preference Library,数据重建机制浅析~