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

1,088 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第25天,点击查看活动详情

接下来会对Preference Library官方库进行一个系列讲解,本篇文章是Preference Library系列的第十篇,主要是介绍Preference Library的多布局设置项实现机制。

设置项多布局如何实现的呢?

这里再说一次,Preference Library就是RecyclerView适配器实现的多布局item,所以实现多布局的原理就藏在RecyclerView.Adapter的方法getItemViewType(),这个说法对不对呢?Preference Library也是这样实现的吗?

我们先回顾下平常业务项目中实现一个简单多布局的思路

  1. 在方法getItemViewType(position)中根据下标索引position返回对应的item布局类型,比如我们上拉加载,界面底部增加一个正在加载中的布局,这个时候position等于数据源size-1时返回一个新的布局类型标识,这里记为B类型;

  2. 在方法onCreateViewHolder()中根据position调用方法getItemViewType()获取布局类型标识,当其为B时,就创建一个加载中的View并绑定到ViewHolder中;

  3. 在方法onBindViewHolder()中根据position调用方法getItemViewType()获取布局类型标识,当为B时,就刷新加载中的View布局对应内容;

Preference Library就不是这样实现的,我们可以检索下getItemViewType()在适配器中的调用位置,发现onCreateViewHolder()onBindViewHolder()中都没有调用这个方法,所以其多布局的显示方式就不是我们想象中的这种了。

那实现多布局的秘密藏在哪里呢,我们看下关键方法onCreateViewHolder():

public PreferenceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    final PreferenceResourceDescriptor descriptor = mPreferenceResourceDescriptors.get(
            viewType);
    //...
    final View view = inflater.inflate(descriptor.mLayoutResId, parent, false);
    //...
    return new PreferenceViewHolder(view);
}

可以看到这个创建的item布局是从PreferenceResourceDescriptor获取的,可以简单理解为这个对象集合就是适配器的数据源,这个对象我们之前的文章有讲,其内部包装了Preference

所以最终创建这个item布局的是最终是通过Preference拿到的布局资源id,随后进行inflate加载的,到了这里,相信你就会明白Preference Library多布局的实现机制了:

通过数据源的每个对象持有这个对象需要创建的item布局资源id,然后在onCreateViewHolder()中根据下标最终拿到这个资源id进行创建布局,并绑定到ViewHolder中。

顺便说一下,这个实现多布局的方式,对于RecyclerView的复用机制而言,不太友好。

这里以其最后一级缓存中的RecyclerViewPool说明

想要复用RecyclerViewPool中的ViewHolder有一个条件就是对应的viewType要相同,viewType就是通过getItemViewType()进行获取的,问题就在这个方法中:

public int getItemViewType(int position) {
    final Preference preference = this.getItem(position);

    PreferenceResourceDescriptor descriptor = new PreferenceResourceDescriptor(preference);

    int viewType = mPreferenceResourceDescriptors.indexOf(descriptor);
    if (viewType != -1) {
        return viewType;
    }
    //...
}

可以看到,这里返回的ViewType类型对应PreferenceResourceDescriptor在集合mPreferenceResourceDescriptors中的索引下标,这个也就导致了每个PreferenceResourceDescriptorviewType都是不相同的,即使两个设置项Preference比如都是EditTextPreference的实例,下标不同viewtype也就不同,那自然也不会发生复用。

总结

本篇文章主要是讲解了Preference Library实现多布局设置项的原理,希望能对你有所帮助。

参考文章

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

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

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