There's three screens. The first is the main screen, the second is a filler screen and the third contains a screen with 4 buttons.
Main screen contains one button that leads to the 2nd screen, 2nd screen contains another button that leads to the 3rd screen.
Images are stored in drawable-hdpi.
The outofmemoryerror occurs when I press the button in the 2nd screen, specifically the android.app.Activity.setContentView in the onCreate on the 3rd screen.
The app works fine if it's only going from the 1st to the 3rd screen but we need to add some screens in between the 1st and 3rd screen.
Here's the logcat:
Edit: I have a S4 (International) but it works fine on a Nexus 5.
It looks like you are loading a bitmap into memory. In an android app you only have about 16 megabytes of ram available, so you can run out of ram very quickly, and an outOfMemoryError will occur.
You can fix this by using the resource id of the image instead of a Bitmap object. For example, use:
setContentView(R.layout.view_id);
where view_id is the id of the view you want displayed.
The use of images inside your activities can lead to occasional OutOfMemoryError, if you don't follow some guidelines.
First of all, take extreme attention when declaring, initializing and using Bitmaps inside you code. These objects are managed by the system in a special way, this is a good place to start if you want to use them efficiently.
Anyway, since you didn't post any code that show the use of Bitmaps, I focused the attention to a single line of your question:
Images are stored in drawable-hdpi.
Are the images stored ONLY in such directory? Well, this is a bad practice and it's a source of memory errors ;)
When you ask Android to initialize a particular Activity, all the images declared inside its XML are loaded from a particular drawable-**** folder, depending on the screen size of the current device.
For example, a mdpi device will start to look inside the drawable-mdpi for the image named img. If it's not found, then it looks with a cascade behaviour inside all of the other drawable folders.
The problem is here: if the img is found in a different folder than drawable-mdpi, first it's scaled by the system to match the scaling factor for mdpi. Hence, another copy of the Bitmap is created.
Since all your images are inside a single, high resolution folder, the scaling operation will be executed by every non-hdpi device that will run your application. This is not good at all (here some docs).
The solution is to create different scaled versions of the same image and store them in multiple folders, like: drawable-ldpi, drawable-mdpi, drawable-hdpi, drawable-xhdpi
There is a convenient tool that does the dirty job: 9 Patch Resizer
Related
I have a problem when starting my app and another one in split screen mode, when my app's window is enlarged over 2/3 size, my main activity restarts, how to prevent it? When I change the size by less than 1/3 nothing happens .... it doesn't restart. Sorry i didn't provide the code.
Activity restarts are common in Android. They happen whenever there's a configuration change. That includes resizes. You can override that behavior in the manifest (at the cost of being unable to switch layouts at different sizes), but you're better off just being able to support them.
To turn them off in the manifest, use android:configChanges="screenSize" on the appropriate activities. This will cause Activity.onConfigurationChanged to be called instead when the screen is reized.
So, I currently have a recycler view with gridlayoutmanager which through a listener loads more bitmaps asynchronously. Problem is, when I scroll too far down, program crashes due to the fact that there's an ArrayList holding 1000+ bitmaps.
I tried to compress bitmaps with an inSampleSize of 8, and to load from the thumbnails, so my guess it that problem resides in the array holding so many bitmaps.
My question is, is there any way I can, say after 200 bitmaps start to delete them from the array without breaking the scroll system? After deleting them, how would I place the Cursor to start getting bitmaps again? I can add a function that after 200 bitmaps gets called, but I need some hints in order to implement it.
I guess this is a very code-independent question, but in case any code is needed you can have a look at this repository.
Thanks.
I have successfully implemented lazy loading of list images and list items in Android listview. I am using Android 4.0+ and Java 7.
The algorithm i followed is:
List data(including image URL) is downloaded from internet as and when user scrolls the list.
When scroll state is idle, list images are loaded.
In the background thread, images are first checked for in the cache. If not present in cache, they are downloaded and stored into the cache.
Lastly image is set to imageview in the listview and adapter is notified.
The only problem is I am not clear about when to recycle bitmaps. I tried using bitmap.recyle() at many places but I got the following error:
java.lang.IllegalArgumentException: Cannot draw recycled bitmap
It is not possible to add that vast code over here. Also there are some privacy issues. Can someone please help me about this?
EDIT
My application size increases from 727 KB (at the time of installation) to 14 MB.
After I recycle my bitmaps, in getView() of adapter I get "cannot generate texture from bitmap ".
Can anyone suggest how to get rid of it?
Recycling a bitmap renders it unusable. Only recycle when you're completely done with it. In your case, that means after it's been evicted from the cache. You'll also want to make sure that none of your existing views reference it.
As of ICS the need to recycle isn't necessary. There are a few instance where you would want to but considering most listview implementations it probably won't be necessary.
You can check out this video by Chet Hasse for more info on reusing bitmaps which would be better if they are the same size. DevBytes: Bitmap Allocation
Bitmap recycling should be performed differently in different versions of Android. It is best to implement in a way that covers the majority of versions.
As others here said, recycle() renders your bitmap unusable, recycle() is meant to be used once you are finished with the bitmap and would like to induce a garbage collection. I think you should use it on your activity onPause()/onStop().
See here for more information:
Managing Bitmap Memory
I would like to develop a Dialog which is composed of 3 steps to guide the user when he launches the app for the first time.
The following image is an example of what I would like to achieve:
1- I would like to know how to add a mark to close the dialog at the top-right corner?
2- How can I implement the small circles at the bottom of the screen that indicates the current step? Can they be created programmatically?
3-Only to be sure, I decided to navigate between the Dialog steps using a ViewFlipper. Is this the right approach?
Thanks in advance.
I would like to know how to add a mark to close the dialog at the
upper right corner?
Don't do that. That looks like it was a straight port from an iphone app. Use the native android dialog containers/buttons.
How can I implement the small dots at the bottom of the screen that
indicates the current step?
What have you tried? There's a million ways of doing this depending on the rest of the workflow.
Only to be sure, I decided to navigate between the dialog steps using
a ViewFlipper. Is this the right approach?
Maybe. It depends what you're displaying. If you're only displaying a single image or something simple, then that might be the best approach. I would create different dialog fragments ( you are using fragments, right?) for the different steps. That way you can automatically push them to the back stack as you move through the workflow.
one of the ways to implement the "little dots on the bottom" is :
include the dots in every image you are creating.
draw one of the dots highlighted in every image
flip through the images in order of the highlighted dots. (or highlight the dots in the order you want to show your images)
but this would make your dots disappear during the images are flipped.
if you want to avoid that :
create two different image views , one acts as a container for the main image, the other as a container for the dots, place the 1st image view above the other.
create a no of images containing just a no of dots, each with one of the dots highlighted
flip through both the imageViews in synchronization
use a "flip animation" in the upper image view
use no animation, or a minimal animation for the dots.
This will produce the desired effect. Hope this helps :-)
I've been learning android programming for some days. I am creating an ebook application which reads images from the drawable folder. I've successfully implemented the pageviewer activity which loads bitmaps using asyncTask in background and shows a text "loading..." until loading is completed.
I wanted to show a pagelist in another activity using gridview so that user can scroll through a grid of pages and select any. I followed the android gridview tutorial and wasnt much problem. But since i have about 50 images in drawable and it seems gridview adapter shows the grid once all images are croped and placed in grid. It takes a lot of time to show the grid and its quite slow on scroll.
I was wondering if there was a better way to show the grid, asynchronously, like show the first item and then the 2nd and so on, instead of waiting for a long time and displaying the grid. I saw some topics like lazy load which seems similar to what i want, but they all show image from web, it was confusing. Hope i can get some sugestions, or if there is any other way.
Have you tried Fedor's Image Lazy Loader?
Here is the link: Lazy load of images in ListView ,
I know you want to implement it for GridView, but still you can refer the ImageLoader class given in the example code.
Update:
You can even try this example Lazy Loading GridView. I haven't tried it, but as i found it, i thought it may be of your help.
The images you show are probably a bit too large to be used with GridView in their current form.
I guess you need the GridView to display thumbnails, so one possible approach would be to store a thumbnail sized copy of every page you have, and use those in the Grid.
You can also try switching hardware acceleration on in the manifest, that might help you with the scrolling once the images are small enough to load them faster. But afaik hw acceleration is only available in 3.0 and up.