简体   繁体   English

Android有效地从Drawable加载图像

[英]Android Load Images from Drawable Efficiently

I'm new to Android development and I've had a lot of difficulty figuring out how to load images efficiently. 我是Android开发的新手,在弄清楚如何有效加载图像方面遇到很多困难。 The short version of my question is as follows: I have some png images in my res/drawable folder. 我的问题的简短版本如下: 我的res / drawable文件夹中有一些png图像。 How can I load these images onto an Android device without risking an OutOfMemory error? 如何在不冒内存不足错误的情况下将这些图像加载到Android设备上?

Here are some more details about my problem and my attempts to fix it: 以下是有关我的问题及其解决方法的更多详细信息:

I've written a very simple program that simply displays one image. 我编写了一个非常简单的程序,只显示一个图像。 Here's the code: 这是代码:

public class TitleScreenActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_title_screen);
}

And here's the code in 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>

Unfortunately, when I run this program on an emulator, I get a java.lang.outOfMemoryError. 不幸的是,当我在模拟器上运行该程序时,出现了java.lang.outOfMemoryError。 I determined the cause of this error to be the image I'm loading from R.drawable.title_screen_logo because the program works fine when I load a different image. 我确定此错误的原因是我从R.drawable.title_screen_logo加载的图像,因为当我加载其他图像时,程序可以正常工作。 What's confusing about this is that the image is an extremely reasonable size considering that I'm only loading one: 183KB. 令人困惑的是,考虑到我仅加载一个图像,该图像的大小非常合理:183KB。 Since I'm only loading one image, I don't understand why it's causing this error. 由于我只加载一个图像,所以我不明白为什么会导致此错误。 Can the error be caused by a property of the image other than size? 错误可能是由于尺寸以外的图像属性引起的吗?

I've spent days researching this issue and have found some half-decent solutions, but none that work perfectly. 我花了几天的时间研究这个问题,发现了一些不错的解决方案,但没有一个能完美地工作。 I've tried using Picasso and made the following modification to my 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);
}

Basically, what this code does is find the width of the device and then resize the image to have that width and the appropriate height (0.736284058685735 is image's height:width ratio. This code works, but I have quite a few issues with this approach: 基本上,此代码的作用是找到设备的宽度,然后调整图像的大小以具有该宽度和适当的高度(0.736284058685735是图像的高度与宽度之比。此代码有效,但这种方法存在很多问题:

  1. It seems excessive/unnecessary to need to do this during runtime for every image I want to load. 在运行时,对于要加载的每个图像,似乎都需要这样做。 Using this approach would greatly decrease my code's readability. 使用这种方法会大大降低我的代码的可读性。
  2. I had to remove android:src attribute on my ImageView so it didn't overload the memory before the Picasso part of the code ran. 我必须在ImageView上删除android:src属性,以便它在代码的Picasso部分运行之前不会使内存过载。 This means the ImageView won't display anything until Picasso puts something in it, and this actually creates a short but noticeable delay in which the screen in just blank after the program opens. 这意味着ImageView在Picasso放一些东西之前不会显示任何内容,这实际上会造成一个短暂但明显的延迟,即程序打开后,屏幕只是空白。
  3. This actually doesn't seem to completely solve the problem; 实际上,这似乎并不能完全解决问题。 it works if I use Picasso to scale the image width down to half of the screen's width (then let the scaling properties of the ImageView scale it back up), but it still creates an out of memory error if I only scale the image down to the full width of the screen. 如果我使用Picasso将图像宽度缩小到屏幕宽度的一半,则可以使用它(然后让ImageView的缩放属性将它放大),但是如果我仅将图像缩小到屏幕宽度,它仍然会产生内存不足错误屏幕的整个宽度。 While scaling to half of the screen's width makes it load, it creates a noticeable loss of quality and it seems like an arbitrary number; 虽然缩放到屏幕宽度的一半会使其加载,但会导致质量明显下降,并且看起来像是任意数字。 I can't guarantee that a device with less memory would be able to load the version scaled to half of its width. 我不能保证内存更少的设备将能够加载缩放到其宽度一半的版本。

Because of these issues, I'm now considering making a bunch of different images that are only the minimum size and resolution necessary to fit on each Android-specified screen size and density (hdpi, mdpi, small, normal, etc.) However, I'm not sure that this will even solve the problem since the image was so small to begin with. 由于这些问题,我现在正在考虑制作一堆不同的图像,这些图像只是适合每个Android指定的屏幕尺寸和密度(hdpi,mdpi,小,普通等)所需的最小尺寸和分辨率。我不确定这是否可以解决问题,因为图像太小了。 I'm not sure how much smaller I can really make it before decreasing quality, and I'm also not sure how much smaller I'd need to make it to avoid the memory errors. 我不确定在降低质量之前可以真正缩小多少,而且也不确定为了避免内存错误而需要缩小多少。 I feel like there must be a better way, but for the life of me I can't find it... 我觉得必须有更好的方法,但是对于我的一生,我找不到它...

您应该使用此链接https://romannurik.github.io/AndroidAssetStudio/nine-patches.html转换png图像(xxhdpi,mdpi等),具体取决于您的设备

The cause is here: 原因在这里:

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

Try delete these two lines. 尝试删除这两行。 Your app just contains a simple image, it should not have anything to do with OutOfMemory error. 您的应用程序仅包含一个简单的图像,它与OutOfMemory错误无关。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM