为 RecyclerView 缓存 Spannable 字符串
Cache Spannable Strings for RecyclerView
我有一个 Recyclerview,它包含很多消息,类似于聊天屏幕。
在每个列表项中,我有一个 TextView
,我在其中设置了 Spannable
个字符串。字符串包含图像和文本,有时只是文本。当有大量字符需要用图像替换时,我必须用 Drawables
替换字符串中的一些字符的方法会变得非常昂贵,一个明显的 jitter/lag 开始出现 onScroll
.我还将昂贵的方法放在 AsyncTask
中,这大大提高了 RecyclerView 的速度。
问题:
是否可以缓存 Spannable
对象及其所有元数据?如果用户向上滚动一两个屏幕然后向下滚动,我想尝试避免每次在屏幕上呈现行时构建 Spannables
。
如果缓存是可能的,我什至会更进一步实现一个 "Pre-Cache" 方法,该方法在单独的线程上构建和缓存 Spannable,因此如果用户上下滚动,它将只是从缓存加载而不是构建它(如果存在)会导致 "faster" 或 "smoother" 用户体验。
可绘制对象
可绘制对象来自 FilePaths
,作为 ImageSpan
插入到 spannable 字符串中,然后在 AsyncTask 中设置为 TextView
。
首先,我建议您查看 RecyclerView
的 setItemViewCacheSize(int)
方法。接下来,如果您的 Spannable
中有很多可绘制对象,也许值得检查一下这些可绘制对象的大小,它们可能太大了。另一个想法是在将项目传递给 bindViewHolder
.
之前预编译整个项目列表
我能够实现我想要的。
-1。创建了 class LruSpannableCache
扩展到 LruCache
并覆盖 sizeOf
方法
@override
protected int sizeOf(Object key, Object value)
{
//The cache size will be measured in kilobytes rather than number of items.
return ((CacheSpannable)value).size() / 1024;
}
-2。创建了一个对象 CacheSpannable
public class CacheSpannable
{
private int key;
private ISpannable text;
// Getters and Setters for key and text...
public int size()
{
return text.length(); //Can also add the byte length for `key`
}
}
-3。最后用 add
和 get
缓存的 spannables
的静态方法创建了一个 class
private static LruCache spannableCache;
private static final int cacheSize = Runtime.getRuntime().maxMemory() / 1024 / 6;
public static void addSpannable(int key, CacheSpannable value)
{
if (spannableCache == null) spannableCache = new LruSpannableCache(cacheSize);
if (getSpannable(key) == null)
{
spannableCache.put(key, value);
}
}
public static CacheSpannable getSpannable(int key)
{
if (spannableCache == null) spannableCache = new LruSpannableCache(cacheSize);
return (CacheSpannable)spannableCache.get(key);
}
然后要使用它,我只需检查 Spannable
是否被缓存(getSpannable(key) != null
),然后将其设置为 TextView
,如果没有,则构建它,添加到缓存并然后将其设置为 TextView
.
下一步是实施磁盘缓存以无限期保留 spannables
我有一个 Recyclerview,它包含很多消息,类似于聊天屏幕。
在每个列表项中,我有一个 TextView
,我在其中设置了 Spannable
个字符串。字符串包含图像和文本,有时只是文本。当有大量字符需要用图像替换时,我必须用 Drawables
替换字符串中的一些字符的方法会变得非常昂贵,一个明显的 jitter/lag 开始出现 onScroll
.我还将昂贵的方法放在 AsyncTask
中,这大大提高了 RecyclerView 的速度。
问题:
是否可以缓存 Spannable
对象及其所有元数据?如果用户向上滚动一两个屏幕然后向下滚动,我想尝试避免每次在屏幕上呈现行时构建 Spannables
。
如果缓存是可能的,我什至会更进一步实现一个 "Pre-Cache" 方法,该方法在单独的线程上构建和缓存 Spannable,因此如果用户上下滚动,它将只是从缓存加载而不是构建它(如果存在)会导致 "faster" 或 "smoother" 用户体验。
可绘制对象
可绘制对象来自 FilePaths
,作为 ImageSpan
插入到 spannable 字符串中,然后在 AsyncTask 中设置为 TextView
。
首先,我建议您查看 RecyclerView
的 setItemViewCacheSize(int)
方法。接下来,如果您的 Spannable
中有很多可绘制对象,也许值得检查一下这些可绘制对象的大小,它们可能太大了。另一个想法是在将项目传递给 bindViewHolder
.
我能够实现我想要的。
-1。创建了 class LruSpannableCache
扩展到 LruCache
并覆盖 sizeOf
方法
@override
protected int sizeOf(Object key, Object value)
{
//The cache size will be measured in kilobytes rather than number of items.
return ((CacheSpannable)value).size() / 1024;
}
-2。创建了一个对象 CacheSpannable
public class CacheSpannable
{
private int key;
private ISpannable text;
// Getters and Setters for key and text...
public int size()
{
return text.length(); //Can also add the byte length for `key`
}
}
-3。最后用 add
和 get
缓存的 spannables
private static LruCache spannableCache;
private static final int cacheSize = Runtime.getRuntime().maxMemory() / 1024 / 6;
public static void addSpannable(int key, CacheSpannable value)
{
if (spannableCache == null) spannableCache = new LruSpannableCache(cacheSize);
if (getSpannable(key) == null)
{
spannableCache.put(key, value);
}
}
public static CacheSpannable getSpannable(int key)
{
if (spannableCache == null) spannableCache = new LruSpannableCache(cacheSize);
return (CacheSpannable)spannableCache.get(key);
}
然后要使用它,我只需检查 Spannable
是否被缓存(getSpannable(key) != null
),然后将其设置为 TextView
,如果没有,则构建它,添加到缓存并然后将其设置为 TextView
.
下一步是实施磁盘缓存以无限期保留 spannables