Calling setImageViewBitmap on RemoteViews causing incredible lag - android

I am creating notification with music controls.
Everything is fine except artwork update.
The original artwork Bitmap is like 1024x1024 pixels or around so. If I call setImageBitmap(, ) for my RemoteViews directly, it causes lags.
If I'm trying to create new, smaller Bitmap via Bitmap#create(), then there is still lag.
So, what am I doing wrong?

Brett is right. However, it looks more like a bug than a feature.
Instead of re-using the same RemoteViews with different bitmap, I re-create RemoteViews every time with new Bitmap and then send it to a Notification. Strangely, this doesn't cause much lag.

I have run into this as well. SetImageBitmap is expensive as it must marshal the bitmap across the IPC boundary. This requires a large alloc in order to store the bitmap in the IPC message, then there's the actual marshaling of a large blob of memory. You will almost always see a GC_FOR_ALLOC message every time you use setImageViewBitmap. And that is a preemptive GC (world-stopping) which is probably where your lag is coming from.
Ideally, you should use setImageViewUri with a file:// Uri, this alleviates the above IPC concerns and is reasonably fast.
So, bottom line, is that if you are setting bitmaps of any significant size (i.e. larger than a small icon), you will see this lag.

Related

how to clear memory when it is full because of using too many backgrounds in android

Hi guys i am new to android and i posted a question a week ago in this link which basically stated that i was getting a java.lang.outofmemory error when i was using a lot of different backgrounds for my activities.
why am I getting errors when I use different backgrounds in xml
So as a new developer I have searched and searched for a solution as to how to clear the memory as i go from activity but none have been clear or precise. Then i stumbled across this site http://androidactivity.wordpress.com/2011/09/24/solution-for-outofmemoryerror-bitmap-size-exceeds-vm-budget/
which described exactly what i was going through except they use 10 activities and i am only using 4. However when i implemented his code it my project i ended up with null pointer exceptions and after fiddling with his code I ended up back were i started with the same out of memory error.
So can anybody direct me to someone who can show me how to have as many backgrounds as i want with out running out of memory. Or does android as great as it is does not let you simply use more than a certain amount of backgrounds? help?
It's not that there is a limit on the amount of backgrounds, but each background image you load is a loaded into memory as a bitmap and held there until the activity is destroyed. If you are opening multiple activities one after another, each background image will need to be held in memory and so eventually you will get an out of memory exception.
If you set a large background image, you will also experience some blocking on the ui thread, while the image is loaded into memory.
One way around this that worked for me was to use an imageloader. This decodes the image off the ui thread, caches it on disk, loads it into memory and if memory is running low, will clear an image from memory and fallback to the disk cache. You may get a slight delay/fade in as the image is loaded but this is not so bad visually, and when loaded once, will load straight away if you go back to that activity.
Check out Picaso Picasso which is really easy to implement and a great api or Universal Image Loader.
My layouts were all RelativeLayouts and the first child (will be behind all other views) was an ImageView with scaleType centercrop and width and height set to match_parent. When each activity loads (onCreate), just grab a reference to the imageview in your layout and set the required background image using your ImageLoader of choice.
The other option is to have multiple copies of your background image in your resources, with each one resized to perfectly fit your resolutions of choice (drawable-mdpi/-hdpi/-xhdpi etc). This way, you ensure you are never loading images that are way bigger than you need to be displayed and your app will be more forgiving in terms of memory consumption.

Loading tall images from url in slivers preventing whole image from loading into ram

I am looking for a library or some idea on how I can load an image by parts from the disk or a url straight to the disk then in parts again to the ram. So the two ways I see that this can be done is loading the whole image onto the disk by reading and writing it from the url directly using the ram only for the buffer then when the image is on the disk some how creating bitmaps of only parts of the image, that way I DO NOT load it all and putting those in a ListView.
The issue is that I am dealing with extremely long images (10K + pixels long w/ a width of 4-600) and they hog up lots of ram if loaded all in one bitmap. I can not just scale them down like the Google android tutorial does in the handling large bitmaps section as that results in a width too small to deal with. So if I can somehow generate small bitmap slivers on the disk I can use them by loading them in a ListView preventing loading the image as a whole into ram.
Right now I am breaking the long images into slivers from a bitmap and I realized that that isn't really accomplishing what I am trying to do as the whole image is loaded into a bitmap in memory and is then broken up, then GC (So I am using up the full abmount of ram anyways). I am testing on a new top of the line android phone and the app works fine, but the heap size reaches 80mb+ with the larger images temporarily in ram as it breaks down the bitmap and this will be an issue with devices that have lower heap limits
You can try using this class, support from 2.3 http://developer.android.com/reference/android/graphics/BitmapRegionDecoder.html
If you are using Java you can work with InputStreamReader and OutputStreamWriter. Method read() accepts the buffer as one of the parameters, its length can be anything suitable. Of course you can create a new file for each buffer being written.
Is it what you're looking for?
edit
well its not. have you seen this Strange out of memory issue while loading an image to a Bitmap object ?
If you have control over the server from where you are fetching data, throw in another field in your response, such that it returns a thumbnail/smaller image. The server can then generate the required thumbnails for you, without you bothering about it.
Decoding bitmaps on the fly might be expensive, most of the times. If you can't change anything on the server, download and save the images, and after saving, generate their corresponding thumbnails and save them as well. In your list, use the thumbnails. Also, save the information about which images have been cached, and whose thumbnails you already have. This might look like a lot of work, but depending on the use case, this can be a better approach dealing with large images.
Problem with downsizing?
Well, you can come up with some kind of logic as to generate thumbnails, based on the original size of the image. For longer(vertically long images), you could use BitmpapRegionDecoder (http://developer.android.com/reference/android/graphics/BitmapRegionDecoder.html) as #Binh Tran has suggested.
Try maybe encoding the image to make the size small.

Trying to display a large image as tiles without hiccups

My tablet app has to display a very large image (2500x6000) and allow the user to pan across, zoom in & out. Since it can't fit into memory I've broken it into tiles and am loading those as needed. The problem I'm running into is that whenever I unload or replace a bitmap I cause garbage collection which pauses my app with noticeable stutter. I was wondering if anyone had come up with any clever ways to work around this? I create my bitmaps using BitmapFactory.decodeResource. I've tried replacing the same bitmap but garbage collection still runs (assuming it dumps the old bitmap and replaces it with a new one).
Thanks!
Figured out the answer! In API11+ BitmapFactory.Options has an attribute called inBitmap which will reuse the bitmap when loading content. I've implemented it as such:
mBg[i] = Bitmap.createBitmap(800, 1232, Bitmap.Config.RGB_565);
mBgOptions[i] = new BitmapFactory.Options();
mBgOptions[i].inBitmap = mBg[i];
mBgOptions[i].inPreferredConfig = Bitmap.Config.RGB_565;
mBgOptions[i].inMutable = true;
mBgOptions[i].inSampleSize = 1;
The garbage collector no longer runs and the pauses have been removed.
As an f.y.i, inSampleSize has to be set or it won't work.
If you are targeting Android 3.0 then this answer may help:
How to load tiles from a large bitmap in Android?
Pre-Android 3.0 you could build an HTML page of your tiled images and let the built-in browser handle the load and unload of the images. My answer here has some more details:
How to tile and scroll a large image (10000x10000) in android
Anyone else have any alternative approaches?
Are you using android:largeHeap="true"? That might reduce the frequency of GCs. Also given you are targeting tablets, then you can safely assume that you are dealing with a concurrent garbage collector. So it will work best if it has more, smaller chunks of memory to collect, i.e. smaller tiles.
I used this easy to integerate source of WorldMap application:
https://github.com/johnnylambada/WorldMap
This uses a huge image of a world map, and uses cache to display a map.
To integerate, I just copied all the java files (5 i guess) and used the surfaceView in my layout file. Then I went through the small OnCreate() method of ImageViewerActivity.java and used the code in my activity (with sligh alteration, depending on my personal use).

The Infamous "Exceeds VM Budget" Issue

So I have an APP that loops and continuously draws many png files to a canvas. In the constructor for the thread, for some of the pngs I declare Drawable and some Bitmap handles and assign them (respectively) like so:
Drawablename = context.getResources().getDrawable(R.drawable.pngresource);
mBackgroundImage = BitmapFactory.decodeResource(res, R.drawable.bckgrnd);
Keep in mind I do both methods, MANY times. (even though most of the images are fairly small)
Well... the problem i'm getting is that when trying to start this app on older devices (specifically like the original droid and older) it force closes with the VM budget error.
From research, I've noticed that this seems to be a common problem. (The app runs fine on all newer devices such as droid x, every tablet at best buy, charge, atrix, etc.)
So my question is could I be doing something better?
Is one of these methods of referencing the pngs superior?
Also What exactly is happening here? I need to be able to reference the Image to draw at any time. In other words, at any given instant I could call Draw on one of the handles.
The fixes I've seen for similar problems involve calling the Garbage collector, but would that help me since I would need the Images later anyway? Or is this exclusively a problem with the way i'm referencing the pngs from the drawable folder?
Sorry if this is confusing, i'm a beginner.
If I called System.gc() after every reference would that help, even though the reference is still stored as a Drawable object?
The common fix:
Resize image size, for example: createScaledBitmap()...
Reduce image quality, Config.inSampleSize setting...
Remove all references to Bitmap objects when un-used (setting references to NULL, of course). If you don't do this, System.gc() will does nothing, remember this! and this method call does not guarantee that the memory will be freed right away.

Android calling GLUtils.texImage2D within onDrawFrame very slow

We are building a scrollable background, and currently have one large background image that we split up into 512x512 tiles, and want to load these tiles as they are needed, instead of all at once, when calling GLUtils.texImage2D within onDrawFrame, we have noticeable lag we think because of having to load the texture onto the hardware, is there a better way to do this?
Thanks.
Use texSubImage2D() to reload existing texture objects instead of creating entirely new ones.
G'day buddy,
I think the sheer amount of image data you're trying to transfer within a frame time is a tad much: if you are using a 24bpp format, 512x512 amounts to 1 MB of data. I can think of two ways to minimize it:
Change to a bitmap format that has less bpp. If you are using ARGB8888 you might want to try switching to RGB565 (as it is a background) to halve the data.
Consider splitting up the 512x512 into e.g. 4 chunks of 512x128 (since you are scrolling vertically). This way you distribute the loading over more frame intervals.
Cheers, Aert.

Categories

Resources