【问题标题】:Android Load Images from Drawable EfficientlyAndroid 有效地从 Drawable 加载图像
【发布时间】:2015-09-19 07:32:00
【问题描述】:

我是 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 是图像的高度:宽度比。这段代码有效,但我有很多问题这种方法:

  1. 对于我要加载的每个图像,在运行时都需要这样做似乎过多/不必要。使用这种方法会大大降低我的代码的可读性。
  2. 我必须在我的 ImageView 上删除 android:src 属性,这样它才不会在代码的 Picasso 部分运行之前使内存过载。这意味着 ImageView 在 Picasso 放入某些内容之前不会显示任何内容,这实际上会造成短暂但明显的延迟,在该延迟中,程序打开后屏幕只是空白。
  3. 这实际上似乎并没有完全解决问题;如果我使用 Picasso 将图像宽度缩小到屏幕宽度的一半(然后让 ImageView 的缩放属性将其放大),它会起作用,但如果我只将图像缩小到屏幕的整个宽度。虽然缩放到屏幕宽度的一半会使其加载,但它会造成明显的质量损失,并且看起来像是一个任意数字;我不能保证内存较少的设备能够加载缩放到其宽度一半的版本。

由于这些问题,我现在正在考虑制作一堆不同的图像,这些图像只是适合每个 Android 指定的屏幕尺寸和密度(hdpi、mdpi、小、正常等)所需的最小尺寸和分辨率。 )但是,我不确定这是否会解决问题,因为图像一开始就很小。我不确定在降低质量之前我真的能把它缩小多少,我也不确定我需要把它缩小多少才能避免内存错误。我觉得一定有更好的方法,但对于我的生活我找不到它......

【问题讨论】:

  • 这里你可以参考android官方文档来高效处理位图developer.android.com/training/displaying-bitmaps/index.html你也可以找缓存
  • 为什么只使用 Drawable 目录而不使用 drawable-ldpi/hdpi/xhdpi 等目录以便更好地使用?
  • 为什么你给imageview的宽度和高度这么多的值“20000dp”,尝试使用'match parent'

标签: java android image memory android-studio


【解决方案1】:

您应该使用此链接转换您的 png 图像(xxhdpi、mdpi 等) https://romannurik.github.io/AndroidAssetStudio/nine-patches.html 根据您的设备自动更换图像

【讨论】:

  • 该链接中有哪些不同的编辑模式?拉伸区域和内容填充有什么区别?
【解决方案2】:

原因在这里:

android:maxWidth="20000dp"
android:maxHeight="20000dp"

尝试删除这两行。您的应用只包含一个简单的图像,它应该与 OutOfMemory 错误无关。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多