Android 进阶学习(三十五) Android 中给View 添加Drawable的思考(二)

问题回顾

在上一篇博客 Android 进阶学习(二十四) Android 中给View 添加Drawable的思考 的结尾处 ,我说出了一个问题,那就是我自己写的drawable 缓存,缓存的是drawable 本身,这就使得不同的View 在使用相同的drawable时,drawable 不适配的情况,比如 RecyclerView 的item 是一个 水平自动填充的item , 如果上一个使用这个drawable 的item 宽度比当前这个item的宽度宽,就会导致当前这个item 的背景drawable 的宽度超过了item的宽度,出现不适配的情况,那么这种情况 源码是如何解决的呢,

@Nullable
  Drawable loadDrawable(@NonNull Resources wrapper, @NonNull TypedValue value, int id,
          int density, @Nullable Resources.Theme theme)
          throws NotFoundException {
          ...省略部分代码
          if (!mPreloading && useCache) {
           这里就是获取缓存的drawable
              final Drawable cachedDrawable = caches.getInstance(key, wrapper, theme);
              if (cachedDrawable != null) {
                  cachedDrawable.setChangingConfigurations(value.changingConfigurations);
                  return cachedDrawable;
              }
          }
        ...省略部分代 
      }
  }

class DrawableCache extends ThemedResourceCache {
  @UnsupportedAppUsage
  public Drawable getInstance(long key, Resources resources, Resources.Theme theme) {
      final Drawable.ConstantState entry = get(key, theme);
      if (entry != null) {
          每次都是利用   Drawable.ConstantState 重新创建一个drawable 
          return entry.newDrawable(resources, theme);
      }
      return null;
  }

}

从源码这里我们可以看到,即使使用的是同样的drawable.xml 文件,每个view 的drawable 都是单独创建的,只不过这个模板只创建了一次,所以我们的缓存也需要缓存 Drawable.ConstantState ,每次获取后,重新创建一个新的Drawable

Drawable 组件化

我们app 在探究组件化的过程中关于drawable 的问题也遇到了不少, 由于组件化开发的过程是先有的app,我们再对app进行组件化拆分,在组件化的初期,很多资源文件都是到处copy 的,虽然我们给组件添加了 resourcePrefix 这个属性,为每个组件的xml 资源命名做了限制,还是造成了不少打最终包成功后样式对不上的问题,而且随着项目越来越大,新写一个drawable 所耗费的时间,比找到一个相同属性的drawable 的xml文件还要快一点,这样就造成了恶性循环,大家就不停的创建新的drawable.xml 文件,找到相同属性的就更难了...

伴随着这样的思考,能不能找到一个摆脱xml来设置背景drawable 的方法就这样诞生了,但是这个过程也遇到了好几个问题

1.也就是上面我们所说的 drawable 缓存的问题,通过缓存 Drawable.ConstantState 每次获取都重新创建drawable 这个问题已经解决了
2.我在最开始的时候为整个项目重新定义了一套 DrawableView ,比如 DrawableTextView , DrawableLinearLayout , DrawableRelativeLayout 等等, 在为每个View 添加属性的时候,就产生了一个问题,那就是


      
      
  


      
      
  

每一个View 在使用 xml 添加drawable 属性的时候,他们属性命名是不同的,LinearLayout 的属性就是 app:ll_zhome_color=""
RelativeLayout 的属性就是 app:rl_zhome_color="",这样就导致了不了解这个机制的人,如果只是copy属性,就会导致使用不了这个问题,那么能不能像 ConstraintLayout 一样, 所有view 的属性名都一致,并且android studio 还会自动提示出属性的名称呢,

这个问题的解决方案自己想一下其实也特别简单,那就是事先将属性声明出来,在自定义View 的 declare-styleable 引用这个属性就可以了,举个栗子


先把这个 属性在 resources  标签下声明出来



      
  


      
  

这样就可以了,虽然在获取属性的时候是根据不同的View 来获取的,但是在编写 layout.xml 的过程中, 属性的命名是一致的,

      

          

      

插个图
动画.gif

下面就是我们在使用过程中经常遇到的属性,我把它们每个属性都标注了出来,方便使用的人来查看并使用相关的属性,


  
      
      
      
      
      
  
  
  
  
  
  

  

  

  

  
  
  
  
  
  

  

  

  

  

  

  


  

  

  

  

  

  


  

  

到了这里整个过程就告一段落了,这个一套drawable 在我们的组件里面已经试用了很长一段时间了,并没有出现什么问题,下面我方一下Github 地址 TsmBottomSheetDialog,这里就能找到相关代码

你可能感兴趣的:(Android 进阶学习(三十五) Android 中给View 添加Drawable的思考(二))