【问题标题】:Efficiency of getDrawable(): is the Drawable cached by the framework?getDrawable() 的效率:Drawable 是否被框架缓存?
【发布时间】:2018-11-07 06:20:54
【问题描述】:

每次单击切换按钮时,我都需要更改它的图像。

这样做有效率吗?

public void onClickToggleButton(View v) {
    if(_on) {
        _on=false;
        myImageView.setImageDrawable(getResources().getDrawable(R.drawable.btn_off));
    } else {
        _on=true;
        myImageView.setImageDrawable(getResources().getDrawable(R.drawable.btn_on));
    }
}

或者这是否意味着每次都会从PNG文件中解码Drawable

在这种情况下,只调用两次 getDrawable()(在 onCreate() 中)并保留我自己对 2 个 Drawables 的引用会更好。

【问题讨论】:

  • 查看源代码grepcode.com/file/repository.grepcode.com/java/ext/…(如果您遵循方法调用,您将最终进入缓存部分并最终进入 BitmapState)(简短的回答是有一个 WeakRef 缓存以避免解码超过只要内存允许,一次)
  • 附带说明,当 android ToggleButton 已经这样做时,您真的不应该 a/ 添加自己的状态,并且 b/ 每次单击它时都更改可绘制对象。相反,使用 StateListDrawable 来定义用于每个状态的可绘制对象(开、关、按下、聚焦、禁用......)
  • 你为什么要自己创建Drawable?调用 setImageResource 会更好。
  • @StephaneMathis 该文档包含有关从 UI 线程调用 setImageResource() 的警告。另外我认为这种方法的效率和我提出的方法没有什么不同。

标签: android performance android-drawable


【解决方案1】:

这不会回答您的问题,如果每次调用此方法是否有效。 但正如@njzk2 所说,您可以在切换按钮上使用 State Selector

我向您复制一个工作示例(我正在使用)。只需通过您的可绘制对象更改可绘制对象的名称即可。

<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:drawable="@drawable/toggle_on" android:state_checked="true" />
  <item android:drawable="@drawable/toggle_off" android:state_checked="false" />
</selector>

在您定义工具按钮的 xml 中,将背景设置为:

android:background="@drawable/toogle_selector"

其中“toogle_selector”是我之前复制的文件的名称。

这样你就可以忘记每次加载drawable的效率了。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    从 Android API 28 源代码开始,当你调用 Resources#getDrawable 时,会调用 ResourceImpl#loadDrawable,它的开头有这个 sn-p:

    // If the drawable's XML lives in our current density qualifier,
    // it's okay to use a scaled version from the cache. Otherwise, we
    // need to actually load the drawable from XML.
    final boolean useCache = density == 0 || value.density == mMetrics.densityDpi;
    

    还有一个由 Android Zygote 进程操作的字段,称为 ResourceImpl 类中的 mIsPreloading。如果 useCache 为真且 ResourcesImpl 未预加载,则使用可绘制对象的缓存版本。还有一些关于缓存 ColorDrawables 和主题 Drawables 的进一步逻辑。

    如果您像我一样需要 Drawable 的深层副本并且这种缓存行为妨碍您,请查看以下相关答案: Deep copy of a Drawable

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-01
      • 2011-08-14
      • 2011-05-07
      • 1970-01-01
      相关资源
      最近更新 更多