Android Load Images from Drawable Efficiently

我的未来我决定 提交于 2020-01-07 06:54:08

问题


I'm new to Android development and I've had a lot of difficulty figuring out how to load images efficiently. The short version of my question is as follows: I have some png images in my res/drawable folder. How can I load these images onto an Android device without risking an OutOfMemory error?

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:

<?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. 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. What's confusing about this is that the image is an extremely reasonable size considering that I'm only loading one: 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:

  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. 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.
  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. 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. 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...


回答1:


you shoud convert your png image (xxhdpi,mdpi etc..) using this link https://romannurik.github.io/AndroidAssetStudio/nine-patches.html automatically image chaged depending upon your device




回答2:


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.



来源:https://stackoverflow.com/questions/32665582/android-load-images-from-drawable-efficiently

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!