我是 Android 开发新手,在弄清楚如何有效加载图像方面遇到了很多困难。我的问题的简短版本如下:我的 res/drawable 文件夹中有一些 png 图像。如何将这些图像加载到 Android 设备上而不会有 OutOfMemory 错误的风险?
以下是有关我的问题以及我尝试解决该问题的更多详细信息:
我编写了一个非常简单的程序,仅显示一张图像。代码如下:
public class TitleScreenActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_title_screen);
}
这是 R.layout.activity_title_screen 中的代码:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="@color/white"
android:layout_height="match_parent">
<ImageView
android:id="@+id/title_screen_logo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:maxWidth="20000dp"
android:maxHeight="20000dp"
android:scaleType="fitCenter"
android:contentDescription="@string/accessibility"
android:src="@drawable/title_screen_logo" />
</RelativeLayout>
不幸的是,当我在模拟器上运行这个程序时,我收到了 java.lang.outOfMemoryError。我确定此错误的原因是我从 R.drawable.title_screen_logo 加载的图像,因为当我加载不同的图像时程序运行正常。令人困惑的是,考虑到我只加载一个图像,该图像的大小非常合理:183KB。由于我只加载一张图像,因此我不明白为什么会导致此错误。该错误是否是由图像大小以外的属性引起的?
我花了几天时间研究这个问题,并找到了一些不太好的解决方案,但没有一个能完美地工作。我尝试使用 Picasso 并对我的 Activity 进行了以下修改:
public class TitleScreenActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_title_screen);
ImageView imageView = (ImageView) findViewById(R.id.title_screen_logo);
DisplayMetrics displayMetrics = new DisplayMetrics();
WindowManager wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
wm.getDefaultDisplay().getMetrics(displayMetrics);
int width = displayMetrics.widthPixels;
Picasso.with(this)
.load(R.drawable.title_screen)
.resize(width, (int) ((width) * 0.736284058685735))
.into(imageView);
}
基本上,这段代码的作用是找到设备的宽度,然后调整图像大小以具有该宽度和适当的高度(0.736284058685735 是图像的高度:宽度比率。这段代码可以工作,但我有很多问题这种方法:
- 在运行时为我想要加载的每个图像执行此操作似乎过多/不必要。使用这种方法会大大降低我的代码的可读性。
- 我必须删除 ImageView 上的 android:src 属性,以便在代码的 Picasso 部分运行之前不会使内存过载。这意味着在 Picasso 将某些内容放入 ImageView 之前,ImageView 不会显示任何内容,这实际上会产生短暂但明显的延迟,在程序打开后屏幕会变成空白。
- 这实际上似乎并没有完全解决问题;如果我使用 Picasso 将图像宽度缩小到屏幕宽度的一半(然后让 ImageView 的缩放属性将其放大),它会起作用,但如果我只将图像缩小到屏幕的整个宽度。虽然缩放到屏幕宽度的一半可以加载,但它会造成明显的质量损失,而且看起来像是一个任意数字;我无法保证内存较少的设备能够加载缩放到其宽度一半的版本。
由于这些问题,我现在正在考虑制作一堆不同的图像,这些图像只是适合每个 Android 指定的屏幕尺寸和密度(hdpi、mdpi、小、正常等)所需的最小尺寸和分辨率。 )但是,我不确定这是否能解决问题,因为图像一开始就很小。我不确定在降低质量之前我真的可以将其缩小多少,而且我也不确定需要将其缩小多少才能避免内存错误。我觉得一定有更好的方法,但我一辈子都找不到......
最佳答案
您应该使用此链接转换您的 png 图像(xxhdpi、mdpi 等..) https://romannurik.github.io/AndroidAssetStudio/nine-patches.html 根据您的设备自动更改图像
关于java - Android 高效地从 Drawable 加载图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32665582/