【问题标题】:Saving an Object containing Bitmap保存包含位图的对象
【发布时间】:2016-04-12 06:48:59
【问题描述】:

我正在开发一个 android 应用程序(第一个应用程序初学者),我正在尝试在应用程序关闭以再次加载时保存数据。

我要存储的数据是书籍列表,每本书都包含信息(作者、日期等)和包含书籍图片的位图。我尝试使用 GSON 将列表转换为 JSON 并存储在 SharedPreferences 中,但由于位图而导致问题。

我应该如何保存文件并在应用启动时再次检索它?

这是代码的简要版本

库类

public class Library {

        private ArrayList<Entry> library ;

        public Library () {
            library = new ArrayList<Entry>();
        }

        public void addEntry( Entry entry ) {
            library.add(entry);
        }

        public void removeEntry ( Entry entry ) {
            if (library.contains(entry))
                library.remove(entry);
            else Log.d ( "Library" , "Entry Not Found");
        }

        public ArrayList<Entry> getLibrary() {
            return library;
        }

        @Override
        public String toString() {
            return "Library{" +
                    "library=" + library +
                    '}';
        }
}

入门类

public class Entry {
    Book book ;
    final LocalDate borrowDate; 
    LocalDate dueDate;

    //some methods for application
}

图书课

public class Book implements Parcelable {

private String title;
private String author;
private String isbn ;
private double rating;
private int ratingCount;
private int pageCount;
private transient Bitmap image;
private String overview;
//some methods 
}

【问题讨论】:

  • 请注意,我使用 Parcelable 在活动之间传输书籍对象,这就是我在 Book Class 中实现 Parcelable 的原因
  • 您可以使用square.github.io/picasso LIBRARY 直接加载图片网址,在这种情况下将网址保存为字符串并在需要时用于加载图片
  • Glide 是什么意思?
  • 你应该保存图片的链接而不是位图。这会消耗更多的空间和处理资源,Large Bitmap会导致OOM。
  • 是的,你可以使用任何图像缓存库,如通用图像加载器、glide 或 Square Picasso。保存位图 >> 编码和解码是不好的方法。

标签: android serialization bitmap gson


【解决方案1】:

使用 Picasso 并直接加载网址,而不是下载并保存为位图

Picasso.with(mContext)
                        .load("imageURL here")
                        .placeholder(R.drawable.default_pic)
                        .error(R.drawable.error_pic)

                        .resizeDimen(100, 100)
                        .centerCrop()
                        .into(holderOrderHistory.mIcon);

【讨论】:

    【解决方案2】:

    不要将位图放在 sharedpreferences 中。保存在文件中。

    如果需要持久化位图,可以将其分配给静态字段。

    您也可以将其转换为 64 位字符串。但这是糟糕的设计(而且我认为这是一个非常缓慢且昂贵的操作!):

    ByteArrayOutputStream baos = new ByteArrayOutputStream();  
    bm.compress(Bitmap.CompressFormat.PNG, 100, baos); //bm is the bitmap object   
    byte[] b = baos.toByteArray();
    String encoded = Base64.encodeToString(b, Base64.DEFAULT); 
    

    ^ 将其保存到 SharedPreferece。现在开始解码:

    byte[] imageAsBytes = Base64.decode(encoded.getBytes());
    ImageView image = (ImageView)this.findViewById(R.id.ImageView);
    image.setImageBitmap(BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length));
    

    【讨论】:

    • 所以在书籍类中我应该完全删除位图,而是在下载位图后压缩它并将其作为字符串存储在类中?然后每当我必须在图像视图中使用它时,我会先进行解码操作?
    • 这是一种非常昂贵的方法。更快的是保存东西。 SharedPreferences... 并不是真的为此而设计的
    • 那我该如何保存呢?那是我原来的问题。它有多贵/多慢?
    • 另外你觉得四新在cmets中的解决方案怎么样?这样做会更好更便宜吗?
    • 如果您从 url 加载图像,他的解决方案可以工作。如果来自另一个来源(文件等),它可能会有所不同。但是,是的,它是另一种解决方案,并且将是更快的代码,因为 Picasso 是一个针对从 Web 加载图像进行了优化的库,旨在减少您遇到的问题(假设您正在从 Web 加载图像)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-14
    • 1970-01-01
    • 1970-01-01
    • 2014-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多