开发者

How do I keep from running out of memory on graphics for an Android app?

I've been working on an Android app in Eclipse, and so far, my program hasn't really grown past midget size. However I've already run into an issue with an Out of Memory error. You see, I've been using graphics comprised solely of bitmaps and PNGs in this program, and recently, when I tried to add a little bit more functionality to the program (mainly including a few more bitmaps and causing an extra sprite to be created), it started crashing in the graphics thread's constructor -> sprite's constructor. When I tracked the problem down, it turned out to be an Out of Memory error that is seemingly caused by adding too many picture files to the program and creating Drawables out of them.

This would be a problem, as I really don't have that many picture resources worked into that program...maybe 20 or so. I haven't even started to include sound yet. These images aren't all that fancy. My questions are this:

1) Are programs for the Android phone really that limited on how much memory they ca开发者_运维知识库n employ, or is it probably something other than the 20-30 resource pictures causing that error?

2) If the memory for Android apps is so awful it can't even handle 20-30 picture resources being loaded into Drawables that exist at the same time, then how in the world are you supposed to make decent graphics and sound for that thing?

Thanks.


As already mentioned by Steve and Paul, the crucial factor is how big your images are. Android applications are limited to 16Mb on standard phones, and 24Mb on hidef phones. That is a hard limit. This severely limits the amount of graphics you have.

It's easy to calculate your graphic size: width x height x size of pixel (16 or 32 bit).

Some tips:

  • You need to check your code carefully for memory leaks. It is extremely easy to leak memory in Android, and if you leak a couple of bitmaps a few times, you'll run out of memory fast. This article may help.
  • Always load your graphics using ARGB_4444 (16bit) if at all possible. That alone, can reduce memory consumption for graphics by a factor 2.
  • Always null and recycle resources if you can, to assist the gc.
  • Try to ensure that graphics are only used once. Having a resource handling class that deals with this can be very useful (at least if you're doing games).


The easiest way is to add these 2 lines to the manifest in to the application tag

android:hardwareAccelerated="false" android:largeHeap="true"

But these are not recommended if you are building a memory efficient App But this really works.


Hmm.... I've written Android apps with a number of static images (namely for frame animation), so reading your question has raised a few questions:

  • What run environment are you using? Is this using an SDK emulator, or are you running on a real phone? If you're in an emulator, you might want to ensure that it's been created with specs that match the phone (even then, it will probably run slower than it would on a phone due to specialized hardware the phone has).

  • Do you need to have all the Drawables loaded at the same time? For example, if you're drawing an image over and over again, do you create a Drawable for each time you draw it, or can your re-use the same Drawable and simply resize an instance of Rect for the actual call?

  • Similarly, can you load them on-demand? E.g. if you have a photo-album app, can you only display photos 1-9, and load photos 10-19 after a user clicks a Next button?

  • Are your images large? High-density?

I realize these are high-level and hard to apply; I don't think I have a great idea of where you're problem might be from the description. I've hit a few snafus myself, and was able to get the most savings by taking a hard look at how often I really needed to use that new keyword, and what was critical to display and what wasn't. I also found the page on optimizing for performance to be very helpful (I'm mostly making games, some examples here).

Good luck!


The size of the graphics you're trying to load is very important. You can easily load several dozen bitmaps if they're small (e.g. 50x50), but you can't do more than a few if each one is big enough to fill the screen. It also depends on what you're trying to do with those images. For example if you're trying to smoothly rotate an image 90 degrees, even something about 300x300px is enough to almost kill the app.

There are a few things you need to do.

  1. Try not to load images until you need them.
  2. Try to reduce their graphics detail if you can. For example, you can decode bitmaps into RGB 565, ARGB_4444 or ARGB_8888 which each take different amounts of memory. Set this using a BitmapFactory.Options object as a parameter when decoding images.
  3. See if you can 'cheat' - for example, it's easier on memory to take one small image and fill the screen with the image repeated over and over (like tiles), than to use one large image. It's also easier to process an image that's a quarter the size you want it to be, but drawn with a 2x scale factor.
  4. Read this article from the developer of Light Racer and his follow-ups to get some insight into how tweaking performance is one of the most difficult but crucial things to do when developing a game.


Memory leaks and creating Drawables without any reason are not an issue, except for something I'll mention in a second. However other things y'all have mentioned are valuable pieces of information. It is a video game I've been trying to make, and so it's kind of impractical, from what I can discern, to be constantly creating and deleting Drawables depending just on whether they're being shown on the screen right that second; for sprites I believe I need to keep stuff loaded until those sprites themselves are eliminated, and not simply off the screen. As for the error, I basically just loaded too many Drawables into memory during the iniation of the program evidently.

Now one thing that I've just now thought about - and this is NOT what caused that particular error, but it would've caused similar ones down the road - is that I was creating an array of drawables for each and every sprite, when I just now noticed that I should only do that for every kind of sprite.

I'll have to look into the precise method of reducing the graphics to 16-bit and stuff, because much of this application won't really need fancy stuff. I think I'll monitor this thread for another couple of days, in case anybody else has any other ideas, and then I'll mark it answered. Thanks guys.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜