setImageResource 总是给出 OutOfMemoryError
setImageResource always gives out OutOfMemoryError
我正在尝试创建一个包含 ImageView 和 3 个 TextView 的 card_layout 的 ListView:
<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;
}
}
这是 onCreate 中 MainActivity 的代码
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 应用程序总是在启动时崩溃,在 setImageResourceID 的适配器的 getView() 方法中出现 OutOfMemoryError。
如果没有 if/else 语句,该应用程序可以正常工作。
我使用的图像是存储在 res\raw 文件夹中的 .jpg 文件。
放
android:largeHeap=true
在清单应用程序标签中
res/raw/
中图像的行为没有很好的记录。我建议将图像放在可绘制资源目录中。如果您想在所有屏幕密度下使用相同的图像,请使用 res/drawable-anydpi/
.
除此之外,请确保您的图像具有合理的分辨率。图像使用的内存量是分辨率的函数,而不是磁盘大小。例如,一张 1536 x 2344 像素的图像将占用 4 * 1536 * 2344 字节 = 14,401,536 字节 = ~14MB。您不太可能拥有那么大的连续空闲内存块。
我正在尝试创建一个包含 ImageView 和 3 个 TextView 的 card_layout 的 ListView:
<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;
}
}
这是 onCreate 中 MainActivity 的代码
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 应用程序总是在启动时崩溃,在 setImageResourceID 的适配器的 getView() 方法中出现 OutOfMemoryError。 如果没有 if/else 语句,该应用程序可以正常工作。 我使用的图像是存储在 res\raw 文件夹中的 .jpg 文件。
放
android:largeHeap=true
在清单应用程序标签中
res/raw/
中图像的行为没有很好的记录。我建议将图像放在可绘制资源目录中。如果您想在所有屏幕密度下使用相同的图像,请使用 res/drawable-anydpi/
.
除此之外,请确保您的图像具有合理的分辨率。图像使用的内存量是分辨率的函数,而不是磁盘大小。例如,一张 1536 x 2344 像素的图像将占用 4 * 1536 * 2344 字节 = 14,401,536 字节 = ~14MB。您不太可能拥有那么大的连续空闲内存块。