Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/179.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 高效地缓存、传递和查看位图_Android_Caching_Bitmap - Fatal编程技术网

Android 高效地缓存、传递和查看位图

Android 高效地缓存、传递和查看位图,android,caching,bitmap,Android,Caching,Bitmap,我有一个新闻提要,其中新闻项包含图像。每个新闻项(在表视图中)从服务器获取一个图像url,并异步/从缓存下载图像 我将使用一些伪代码/Java以尽可能简单的术语解释我的过程 NewsItemAdapter Map<String, Bitmap> imageCache = new HashMap<String, Bitmap>(); // init cache String imurl = get image url from appropriate NewsObject

我有一个新闻提要,其中新闻项包含图像。每个新闻项(在表视图中)从服务器获取一个图像url,并异步/从缓存下载图像

我将使用一些伪代码/Java以尽可能简单的术语解释我的过程

NewsItemAdapter

Map<String, Bitmap> imageCache = new HashMap<String, Bitmap>();  // init cache
String imurl = get image url from appropriate NewsObject;
Bitmap value = imageCache.get(imurl);

if (value != null) {   // if bitmap is in cache

    load bitmap into image view from cache;
    add bitmap to NewsObject for accessing later;

}else {

    execute Asynchronous bitmap download task;

}
main活动

setOnNewsItemClickListener{

    intent = get intent to mainNewsScreen; //after you click on news item
    intent.putExta("newsBitmap", bitmap from NewsObject); // set in NewsItemAdapter
    startActivity(intent);

}        
主新闻屏幕

onCreate(){

    load bitmap from intent extras into image view;

}
我的主要问题是,如果我删除了找到的
scaleDownBitmap()
方法,那么我就会得到内存错误

但我正在失去很多图像质量。正如您所看到的,我根本没有使用
bitmap.recycle()
,我不完全确定在哪里使用它,因为我需要将图像保存在内存中(我原以为)


你知道如何提高效率吗。我相信这对很多尝试创建类似应用程序的人都会有帮助。

考虑改用lrucache,并在图像从缓存中掉出时将其存储在磁盘上

此处介绍了最佳实践:

将此代码视为一个想法,其中一些是从上面的链接复制的:

...
// Get max available VM memory, exceeding this amount will throw an
// OutOfMemory exception. Stored in kilobytes as LruCache takes an
// int in its constructor.
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);

// Use 1/8th of the available memory for this memory cache.
final int cacheSize = maxMemory / 8;

mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
    @Override
    protected int sizeOf(String key, Bitmap bitmap) {
        // The cache size will be measured in kilobytes rather than
        // number of items.
        return bitmap.getByteCount() / 1024;
    }
    @Override
    protected void entryRemoved (boolean evicted, K key, V oldValue, V newValue) {
       // Save your entry to disc instead
    }
};
。。。
//获取最大可用VM内存,超过此数量将抛出
//OutOfMemory异常。当LruCache接受
//int在其构造函数中。
final int maxMemory=(int)(Runtime.getRuntime().maxMemory()/1024);
//将可用内存的1/8用于此内存缓存。
最终int cacheSize=maxMemory/8;
mMemoryCache=新的LruCache(缓存大小){
@凌驾
受保护的int-sizeOf(字符串键、位图){
//缓存大小将以KB为单位,而不是以字节为单位
//项目数量。
返回bitmap.getByteCount()/1024;
}
@凌驾
受保护的void entryRemoved(布尔逐出、K键、V oldValue、V newValue){
//将您的条目保存到光盘
}
};
Google制作了一个DiscLruCache,您可以简单地下载并在项目中使用(上面的链接描述了它的用法):

也不要在视图中保存无限多的新闻/图像。当用户滚动浏览并阅读新闻条目时,您必须删除它们

考虑使用回收器视图(如果你想让你的应用程序有一种材料设计的感觉,还可以使用卡片):




太好了,谢谢你的回答!将位图传递给intent怎么样?我是否最好传递对全局位图的引用并手动回收它?或者我所做的是真正有效的方法吗?我尽量避免手动回收位图,这是在询问状态问题和对它们的长期引用。Android会自动回收你的位图,并在最后一次引用丢失时释放所有相关内存(你必须用位图手动处理本机内存的日子已经过去),我也会避免通过意图传递位图,而是在活动之间共享缓存。实现这一点的一种方法是将缓存设为单例,在应用程序中共享。请记住,如果选择此方法,可能需要手动调用executeAll();在适当的情况下,不要占用太多的RAM。最后,您可能需要考虑片段方法而不是基于活动的方法。这样你就可以在你的活动中存储LruCache,并在你的片段中访问它。在我接受你的回答之前,有几个问题:首先,新闻将被限制在大约50个项目,所以回收仍然是必要的吗?第二,你能详细说明为什么我应该使用单例变量而不是全局变量吗?我对这东西已经够新了。第三。如果我使用的是片段,我是否需要使用单例呢?谢谢!
...
// Get max available VM memory, exceeding this amount will throw an
// OutOfMemory exception. Stored in kilobytes as LruCache takes an
// int in its constructor.
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);

// Use 1/8th of the available memory for this memory cache.
final int cacheSize = maxMemory / 8;

mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
    @Override
    protected int sizeOf(String key, Bitmap bitmap) {
        // The cache size will be measured in kilobytes rather than
        // number of items.
        return bitmap.getByteCount() / 1024;
    }
    @Override
    protected void entryRemoved (boolean evicted, K key, V oldValue, V newValue) {
       // Save your entry to disc instead
    }
};
<!-- A RecyclerView with some commonly used attributes -->
<android.support.v7.widget.RecyclerView
    android:id="@+id/my_recycler_view"
    android:scrollbars="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

    // use a linear layout manager
    mLayoutManager = new LinearLayoutManager(this);
    mRecyclerView.setLayoutManager(mLayoutManager)
<!-- A CardView that contains a TextView -->
<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_gravity="center"
    android:layout_width="200dp"
    android:layout_height="200dp"
    card_view:cardCornerRadius="4dp">

    <TextView
        android:id="@+id/info_text"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</android.support.v7.widget.CardView>