setImageResource всегда выдает OutOfMemoryError - PullRequest
0 голосов
/ 03 сентября 2018

Я пытаюсь создать ListView с card_layout, который принимает ImageView и 3 TextViews:

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="80dp"
android:orientation="horizontal">
<ImageView
    android:id="@+id/book_cover"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="2"/>
<LinearLayout
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="8"
    android:orientation="vertical">
    <TextView
        android:id="@+id/book_author"
        style="@style/subheading_style"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <TextView
        android:id="@+id/book_title"
        style="@style/heading_style"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <TextView
        android:id="@+id/book_completion_status"
        style="@style/third_heading_style"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>

Заполнение карты объектами CardItem

public class CardItem
{
private String bookAuthor;
private String bookTitle;
private String bookCompletionStatus;
private int bookCoverResID;

/*
* Constructors
*/
public CardItem(String bookTitle)
{
    this.bookTitle = bookTitle;
    bookCoverResID = 0;
}

public CardItem(String bookTitle, String bookAuthor, String bookCompletionStatus)
{
    this.bookAuthor = bookAuthor;
    this.bookTitle = bookTitle;
    this.bookCompletionStatus = bookCompletionStatus;
    bookCoverResID = 0;
}

public CardItem(String bookTitle, String bookAuthor, String bookCompletionStatus, int bookCoverResID)
{
    this.bookAuthor = bookAuthor;
    this.bookTitle = bookTitle;
    this.bookCompletionStatus = bookCompletionStatus;
    this.bookCoverResID = bookCoverResID;
}

/*
* Getters and Setters
*/
public String getBookAuthor() {
    return bookAuthor;
}

public void setBookAuthor(String bookAuthor) {
    this.bookAuthor = bookAuthor;
}

public String getBookTitle() {
    return bookTitle;
}

public void setBookTitle(String bookTitle) {
    this.bookTitle = bookTitle;
}

public int getBookCoverResID() {
    return bookCoverResID;
}

public void setBookCoverResID(int bookCoverResID) {
    this.bookCoverResID = bookCoverResID;
}

public String getBookCompletionStatus() {
    return bookCompletionStatus;
}

public void setBookCompletionStatus(String bookCompletionStatus) {
    this.bookCompletionStatus = bookCompletionStatus;
}

/*
* misc. methods
*/
public boolean hasBookCover()
{
    return (bookCoverResID!=0);
}
}

И использование CardItemAdapter для заполнения списка

public class CardItemAdapter extends ArrayAdapter<CardItem>
{
public CardItemAdapter(@NonNull Context context, int resource, @NonNull List<CardItem> objects) {
    super(context, resource, objects);
}

@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent)
{
    View tempView = convertView;
    if(tempView == null)
        tempView = LayoutInflater.from(getContext()).inflate( R.layout.card_layout, parent, false);

    TextView bookAuthor = tempView.findViewById(R.id.book_author);
    TextView bookTitle = tempView.findViewById(R.id.book_title);
    TextView bookCompletionStatus = tempView.findViewById(R.id.book_completion_status);
    ImageView bookCover = tempView.findViewById(R.id.book_cover);

    bookTitle.setText(getItem(position).getBookTitle());

    if(bookAuthor != null)
        bookAuthor.setText(getItem(position).getBookAuthor());

    if(bookCompletionStatus != null)
        bookCompletionStatus.setText(getItem(position).getBookCompletionStatus());


    if(getItem(position).hasBookCover())
        bookCover.setImageResource(getItem(position).getBookCoverResID());
    else
        bookCover.setVisibility(View.GONE);

    return tempView;
}
}

Это код из MainActivity внутри onCreate

ListView listView;
ArrayList<CardItem> cardItems = new ArrayList<>();
cardItems.add(new CardItem("Origin", "Dan Brown", "Completed"));
    cardItems.add(new CardItem("A Column of Fire"));
    cardItems.add(new CardItem("People vs Alex Cross", "James Patterson",
            "Completed", R.raw.people_vs_alex_cross));

    listView = findViewById(R.id.list_view);
    listView.setAdapter(new CardItemAdapter(this, R.layout.activity_main, cardItems));

При запуске приложения Android всегда происходит сбой, что дает мне метод OutOfMemoryError в getView () адаптера в setImageResourceID. Приложение работает нормально без этого оператора if / else. Изображение, которое я использую, представляет собой файл .jpg, сохраненный в папке res \ raw.

Ответы [ 2 ]

0 голосов
/ 03 сентября 2018

Поведение изображений в res/raw/ недостаточно документировано. Я рекомендую помещать изображения в каталоги ресурсов для рисования. Если вы хотите использовать одно и то же изображение на всех плотностях экрана, используйте res/drawable-anydpi/.

Кроме того, убедитесь, что ваше изображение имеет разумное разрешение. Объем памяти, используемой изображением, является функцией разрешения, а не размера на диске. Например, изображение размером 1536 x 2344 пикселя будет занимать 4 *1536* 2344 байта = 14 401 536 байтов = ~ 14 МБ. Маловероятно, что у вас будет непрерывный свободный блок памяти такого большого размера.

0 голосов
/ 03 сентября 2018

Put

android:largeHeap=true

В манифесте приложения тег

...