2017-08-14 21 views
1

我不清楚如何在缓存方面处理Android图像。假设我有一个应用程序 ,这个应用程序的深度为3级(所以它有3个活动在 之间互相推送)。Android - 处理作为解决方案一部分的图像和下载的图像

如果我的3个活动中的每一个在所有3个活动的工具栏中显示3个图像,我的理解是相同的3个图像将在内存中加载3次。这导致9张图像记忆虽然只有3张图像,但它们只是多次加载 。

另外,假设我的主要活动有一个ListView,显示有关通过网络检索的文档的信息。

每个列表视图项被定制为显示3个信息:

  • 表示类型的文档的图像(即txt文件,.PDF,.DOCX,的.js,...)
  • 代表标题
  • 字符串代表的一些描述

如果上面的ListView加载一个字符串万件(每一个代表一个文件),并承担一切都是一个Word文档,然后.D所有万张图片ocx类型被下载,但它确实只是我需要的一个图像。这似乎是显而易见的网络带宽和内存浪费,我只想下载一张图片并使用它一百万次,而不是下载数百万张图片,每次只使用一次。

因此,在这样的情况下,我不知道我需要什么样的图像,因此没有它在图像资产,但依靠下载的图像来显示文档类型,是否有某种缓存策略,我可以用来避免不得不下载相同的图像百万次?

它是否已经由Android提供?

UPDATE

以我的工具栏的图像的上面的例子中,这些是Android的资源的图像(因此,图形)。所以,对于这些,我相信这些默认缓存?

然而,ListView的图像是从网络下载,所以在我的例子与以上组成3个视图(一个图像和2个标签),则图像将在同一时间的ListView下载定制的ListViewItem正在图像渲染。我提供了一个简单的ListView项目只有3个视图,但它可以是10个视图(比如4个图像和6个标签)。重点是在ListView的渲染过程中从Web下载一个图像。由于该图像可能重复,如何避免下载相同的图像,但使用缓存的图像?

回答

1

首先对项目

ListView名单并不在你认为这样一个低效的方式工作。但如果你真的关心效率和处理真正大量的数据列表,建议使用RecyclerView。与here的比较有很好的讨论和答案。

如果您计划处理数千个文档的列表,其中包含某些有限的文档类型图标集合,最佳做法是创建一个位图HashMap,您将链接到特定的列表项目(无论您将会选择使用:RecyclerViewListView)。

下面是一个简单的例子(这是不正确的java,只给一个想法)与列表视图适配器类:

public class DocumentsListAdapter extends ArrayAdapter<String> { 
    private final HashMap<String, Bitmap> docIcons = HashMap<String, Bitmap>() 
    private final Activity mContext; 
    private final List<String> mItems; 

    public DocumentsListAdapter(Activity context, List<String> items) { 
     docIcons.put("docx", loadDocBitmapFromDisk()); 
     docIcons.put("xls", loadXlsBitmapFromDisk()); 
     docIcons.put("pdf", loadPdfBitmapFromDisk()); 
     // and so on... 
     mItems = items; 
     mContext = context; 

    } 

    @Override 
    public View getView(int position, View view, ViewGroup parent) { 
     LayoutInflater inflater = context.getLayoutInflater(); 
     View rowView= inflater.inflate(R.layout.list_single, null, true); 

     TextView txtTitle = (TextView) rowView.findViewById(R.id.txt); 
     ImageView imageView = (ImageView) rowView.findViewById(R.id.img); 

     txtTitle.setText(mItems.get(position)); 

     if(items.get(position).endsWith(".docx")) { 
      imageView.setImageBitmap(docIcons.get("docx")) 

     } // and so on for other types... 
    } 
} 

这个例子不包括你如何获得你的图标。您可以从互联网上下载它们,将它们存储在磁盘上,当应用程序需要这些图标时 - 您可以将它们从磁盘加载为位图,并将每个位图存储在内存中一次,然后在视图中重新使用它们。与RecyclerView一起实现这个逻辑,您将获得相当高效的应用程序,不浪费内存并且响应速度非常快。

你不必存储HashMap在适配器的位图,但它是,如果你只在一个地方使用它不错的选择。如果你需要在不同的活动中使用它,然后再考虑保持这个HashMap别的地方,它不会被利用类似于ListViews不同活动之间的每一次用户交换机重新加载。

处理与相同的图像

多个活动关于这取决于你如何存储图像的活动。如果它们也从互联网下载并缓存在磁盘上,则可以按照本答案的ListView部分所述执行相同操作。只需保留已加载到内存中的图像列表并使用

imageView.setImageBitmap(someBitmap) 

当您需要将其显示在活动的特定部分时。

在你的应用程序的资源正在运行的情况是,更容易,因为你可以做这样的事情:

Drawable dr = context.resources.getDrawable(R.drawable.my_favourite_image); 
imageView.setImageDrawable(dr); 

内存高效地使用所有的工作都在抽油烟机下在这里完成。

如何避免下载相同的图像,但使用缓存一个

这取决于你如何去跟踪每个图像的独特性。例如。如果每个图像具有唯一的URL,最基本的解决方案是使用HashMap和图像的URL作为关键字。

更复杂,但更灵活,更正确的决定是使用类似Guava缓存工具。这不是针对Android的具体问题,而是非常广泛的主题,但您可以在take a look here

虽然如果您计划混淆图像的复杂布局并关心性能,请检查Ankothis benchmark。这与内容缓存无关,但布局渲染性能可以提高3倍甚至更多。

+0

感谢克劳斯,但你能不能把服用看看我添加更新部分。我只想澄清我的意思。非常感谢 – pixel

+1

@pixel我更新了答案。正如我曾经说过的,缓存逻辑很大程度上取决于您需要哪些选项来识别独特的缓存部分以及如何让缓存保持最新状态。这是关键。没有这些信息,很难做出最佳决策。 –

+0

谢谢克劳斯,我想我现在明白了,谢谢你的伟大解释。就我而言,唯一性可以通过在这种情况下扩展文档(即docx,.pdf,.txt,.js,...)来确定,并且缓存永远不会过期,因为文档不会改变我猜的类型。另外,我不会先下载图像并将它们保存到磁盘,然后将它们加载到列表中。我准备好接受你的回答,只要告诉我你是否必须根据此评论添加内容。非常感激。 – pixel