我正在構建一個用於播放音頻書籍的Android應用程序。使用FirebaseRecyclerViewAdapter的OutOfMemoryError
root
--- audioBooks
--- <individual hash for each book>
--- author: "Ray Bradbury"
--- title: "Fahrenheit 451"
--- finished: false
--- key: <individual hash for each book>
--- cover
--- b64Cover: <b64-encoded image>
--- backgroundColor: -14473711
--- ...
--- tracks
--- 0
--- title: "Track 1"
--- duration: 361273
--- finished: false
--- currentPosition: 12345
--- ...
--- 1
--- ...
--- currentTrack
--- title: "Track 1"
--- duration: 361273
--- finished: false
--- currentPosition: 12345
--- ...
我有聲書,AudioBookTrack和AudioBookCover爲更好地瞭解三個模型類(去除getter和setter方法:有聲讀物元數據(標題,作者等)用以下結構存儲在數據庫火力地堡)。
public class AudioBook {
private String title;
private String author;
private int duration;
private boolean finished;
private String key;
private AudioBookCover cover;
private ArrayList<AudioBookTrack> tracks;
private AudioBookTrack currentTrack;
public AudioBook() {
}
public AudioBook(String title, String author, boolean finished, String key, AudioBookCover cover, ArrayList<AudioBookTrack> tracks, AudioBookTrack currentTrack) {
this.title = title;
this.author = author;
this.finished = finished;
this.key = key;
this.cover = cover;
this.tracks = tracks;
this.currentTrack = currentTrack;
}
}
public class AudioBookTrack {
private String title;
private String album;
private String author;
private String filePath;
private int duration;
private int currentPosition;
private int index;
private boolean finished;
private String key;
public AudioBookTrack() {
}
public AudioBookTrack(String title, String album, String author, String filePath, int duration, int currentPosition, int index, boolean finished, String key) {
this.title = title;
this.album = album;
this.author = author;
this.filePath = filePath;
this.duration = duration;
this.currentPosition = currentPosition;
this.index = index;
this.finished = finished;
this.key = key;
}
}
public class AudioBookCover {
private String b64Cover;
private int backgroundColor;
private int primaryColor;
private int secondaryColor;
private int detailColor;
public AudioBookCover() {
}
public AudioBookCover(String b64Cover, int backgroundColor, int primaryColor, int secondaryColor, int detailColor) {
this.b64Cover = b64Cover;
this.backgroundColor = backgroundColor;
this.primaryColor = primaryColor;
this.secondaryColor = secondaryColor;
this.detailColor = detailColor;
}
}
使用Firebase數據庫中的數據並將其轉換爲模型類可以毫無問題地工作。不過,我現在想用FirebaseRecyclerViewAdapter在RecyclerView中列出所有的音頻書籍。這是代碼,在一個片段的onCreateView執行()方法:
mAudioBooksList = (RecyclerView) view.findViewById(R.id.audiobooks_list);
mAudioBooksList.setHasFixedSize(true);
ref = new Firebase(Constants.FIREBASE_URL).child("audioBooks");
mAdapter = new FirebaseRecyclerViewAdapter<AudioBook, AudioBooksViewHolder>(AudioBook.class, R.layout.audiobook_grid_item, AudioBooksViewHolder.class, ref) {
@Override
public void populateViewHolder(AudioBooksViewHolder audioBooksViewHolder, AudioBook audioBook) {
audioBooksViewHolder.author.setText(audioBook.getAuthor());
audioBooksViewHolder.title.setText(audioBook.getTitle());
try {
byte[] byteArray = Base64.decode(audioBook.getCover().getB64Cover());
Bitmap coverBitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
audioBooksViewHolder.cover.setImageBitmap(coverBitmap);
}
catch(IOException e) {
Log.e(TAG, "Could not decode album cover: " + e.getMessage());
}
}
};
mAudioBooksList.setAdapter(mAdapter);
這是ViewHolder:
private static class AudioBooksViewHolder extends RecyclerView.ViewHolder {
TextView author;
TextView title;
ImageView cover;
public AudioBooksViewHolder(View itemView) {
super(itemView);
author = (TextView)itemView.findViewById(R.id.audiobook_grid_author);
title = (TextView)itemView.findViewById(R.id.audiobook_grid_title);
cover = (ImageView) itemView.findViewById(R.id.audiobook_grid_cover);
}
下面這段代碼通常工作(我可以看到在屏幕上所顯示的值),非常短的時間後然而,應用程序崩潰由於存儲器外的一個錯誤:
Uncaught exception in Firebase runloop (2.4.0). Please report to [email protected]
java.lang.OutOfMemoryError: Failed to allocate a 35116844 byte allocation with 16773184 free bytes and 32MB until OOM
at java.lang.StringFactory.newStringFromChars(Native Method)
at java.lang.AbstractStringBuilder.toString(AbstractStringBuilder.java:629)
at java.lang.StringBuilder.toString(StringBuilder.java:663)
...
我測試上的物理的Nexus 5(無仿真器應用程序)。 我想這是因爲我的嵌套模型(AudioBookTracks裏面的AudioBooks),導致數百個Java對象。不幸的是我不知道如何解決這個問題。只列出音頻書籍,我不需要他們相應的音頻書籍音軌,但是音頻書籍音軌是音頻書籍的子元素,它們也被轉換爲Java對象。 另一方面,我也嘗試通過使用ref.limitToFirst(2)來限制正在顯示的有聲讀物的數量。該應用程序仍然崩潰,但它需要更多的時間。
您是否看到任何可能導致問題的代碼問題?或者是否有可能只從Firebase數據庫中選擇我需要的值,例如跳過有聲書的軌道?
謝謝!
非常感謝!我按照你的建議改變了我的數據模型,現在它工作正常。 – BGoll