I'm developing an app that displays a step-by-step process for my company. Each step consist of one image and each activity shows eight to twelve images. I'm now running into the java.lang.outofmemory. It's also listing an android.view.InflateException:Binary xml error. I've resized the images to 360dpi and that only allowed a few more pics before reaching the error again. I also tried increasing the heap size, which did not change the result. Is there another way I should do this? Thanks a lot.
You can scale down the Image, thus reducing their memory footprint. Also, you could look into certain libraries like picasso and UIL and see if they can help you.
No magic here, i guess the imageview are rendering in full argb mode, so 8 bit * 4 * number of pixels. That's a lot!
How does your activity displays images ?
If they are in a list, make sure to use recycling.
http://developer.android.com/training/improving-layouts/smooth-scrolling.html
You are interested in the ViewHolder
If you are using a ViewPager and swipes left/right, make sure to destroy your fragments while you are swiping, so that you can have in memory only 3 images (1 displayed, and 2 next to it).
If it's none of those, maybe you will have to refactor your layout :(
Last but not least, make sure to resize your bitmap to your exact screen size, as suggested before, Picasso provides a convenient mean to do it with .fit(). It will wait for the imageview to be measured, then resize the downloaded bitmap and fit it in the imageview. You don't even have to worry about networking on main thread, how wonderful !
Picasso.with(getActivity())
.load(imageUrl)
.fit()
.into(imageView);
This is where coding approach matters. How you've implemented it might help us pin point the memory leaks.
But a general practice ( maybe not good one)
Load all Bitmaps in a constant class. ( just once)
Refer infinitely.
Related
I'm starting to learn Java and i came across an excersize where i need to fade away one image and display by fading in another image.
My solution to this excersize is to have one imageView and fading out the first image, then switching the image source to the second image and fading the imageView in so it should display the new image. Doing that so it will display all the images i want by fading out then in with a new image.
this is my code for the program:
public void fade(View view){
ImageView simpsonImageView = findViewById(R.id.simpsonsImageView);
simpsonImageView.animate().alpha(0f).setDuration(3000);
simpsonImageView.setImageResource(R.drawable.bart);
simpsonImageView.animate().alpha(1f).setDuration(3000);
simpsonImageView.animate().alpha(0f).setDuration(3000);
simpsonImageView.setImageResource(R.drawable.lisa);
simpsonImageView.animate().alpha(1f).setDuration(3000);
}
Now i have seen in the tutorial i'm learning from that the tutor used different imageView for each image. I wanted to know which solution is correct or at least acceptable amoung these two. Or it dosent really matter and that both solutions are fine.
There is one thing which you can only achieve when using two ImageViews: you can crossfade the two images so that the screen is never entirely empty.
In the context of your exercise however, you only want to exchange images sequentially.
From a performance point of view, one ImageView may be better than two because it will obviously take less memory and CPU time but I doubt that this will have a noticeable impact on modern devices.
So as long as you don't animate lots of pictures simultaneously (think of football teams instead of the Simpsons), both solutions are fine.
Please note that with your code as-is there will be no animation visible at all and the ImageView will appear to only show the second picture. This is because animate() triggers an animation but it does not wait until the animation is finished. So you need to work with an AnimationListener or use Handler.postDelayed() to swap pictures and start the next animation only as soon as the previous one is finished.
I'm developing and Android application, but I have some doubts about the
feasibility of my project.
I have to implement a custom layout composed from a ImageView that show an image, in particular a VectorDrawable.
Overlapping the ImageView there is a SurfaceView that :
Capture every coordinates of the touches;
Draw a Bitmap (in a certain position) everytime I touch the screen.
The purpose is to show a background image and use it as a reference, each time the user touches the screen a marker on SurfaceView must be inserted, this technique allows to simulate the insertion of a marker on an image.
The question is:
There are other better method to do this?
I have implemented yet, the idea works, but I have some limitation about the SurfaView (for example I can't insert it in a ScrollView).
And at last:
Taking into consideration the reasoning made up to now, assuming to have a ImageView that show a VectorDrawable, is it possible create a function that magnify and lessen the image (VectorDrawable)?
p.s. I apologize for having put two questions but the whole is closely related, I thought it was foolish to open two threads
Task 1: Your task is doable using a SurfaceView but I'm assuming that after you draw your image you would want it to stay if that is the case you may have to keep track of each image separately. If your task is just drawing an image you can also override a View which can do the same task but will also provide transparency and basic layout implementations. Difference between View and SurfaceView is performance, SurfaceView is pretty low level with a double buffer and gives you more control. Also if the number of images are small you can override a FrameLayout and spawn ImageView. Its not very efficient but it will be easier to implement.
Task 2: You can scale an ImageView easily by using setScaleX and setScaleY. But this may pixelate the image. Loading a large Bitmap then drawing it on a custom view would be a better way.
Currently I seek a solution to simple situation, which appeares to become tricky. I need 7 togglebuttons in android app, which are a simple black circles, but I need them to be in the row and fill parent (screen) horizontally. As a resource I use big .jpeg image of a circle. To make them fill all screens in the same mode, I put them into LinearLayout with
#android:layout_width = "fill_parent";
#android:layout_height = "wrap_content";
#android:weight="70";
Weight is 70, so each button received 10. The problem is that source image is too big, which unfortunately results in...this:
(because I dont have enough reputation for posting images, here is the link
http://postimg.org/image/f8wvs5si1/ )
Sorry for small amount of code and this picture taken via phone, I do not have an internet access on the computer with eclipse and this project for some time. I tried of course to change layout_height on other possibilites, but it didnt work. I could put a weight sum also on the vertical position, but on different screens it wouldn't look same.
I also tried to change the height programmatically in onCreate method,
buttonX.setHeight(buttonX.getWidth());
or do the same with a layout, but nothing helped
Perhaps the question is dumm, but I would be glad to hear some ideas.
This is due to screen density variations. There are several things you can do to fix this:
Use different images for each density (but I'm assuming you're looking for another solution)
Use DisplayMetrics to get the actual width of the screen and then set width/height accordingly.
This code:
buttonX.setHeight(buttonX.getWidth());
probably doesn't work because you are calling it before the layout is drawn, and therefore the width is not the drawn width. You can fix this using ViewTreeObserver like here:
How can you tell when a layout has been drawn?
Use an XML attribute like scaleType="centerFit" Personally, I find these confusing because scaleType attributes don't always seem to behave the same way to me. You might have to try different ones, but sometimes they come in handy if you need an XML only solution.
This is my first post and i have (i think) a uncommon request...
I'm programming on the last Eclipse Mac, for every android SDK, and i'm using more XML for layout than runtime... So i search a solution in XML if possible.
Here is the situation: i work with an image background wich simulate item like buttons, image, text... etc. On this image, i put buttons, image, and text (buttonview textview etc...) and place it precisely on their places on the image. This solution is very powerful to have good design BUT, if i change the resolution of the screen, and/or its size, each item won't be at its place, and will be translated (horiz and/or vertic) for some "dp"... (and yes i use dp, not mm or px or whatever)
I'm really embarrased because i think thanks to "dp" it keep proportionnality but.. not !
My question is how can i fix my items at their places on the image background, for different screen size/resolution !!
Thanks in advance everyone,
My Best From Lyon,France
First realise that if you want to make it pixel perfect for all screen sizes your out of luck.
Second accept that you can't make it perfect for all screen sizes.
Third you can get far with creating different layout for different screen sizes. You can read a lot about supporting multiple screen sizes here. One important thing to take from here is that you can make layout for the different screen sizes or different density sizes.
I am developing a game on android.Like tower defense.
I am using surface view.I am using some image as bitmap.(Spritesheets, tilesets, buttons, backgrounds,efects vs.)
Now images are nearly 5-6 mb.And i get this error when i run my game:
Bitmap size exceeds VM budget
19464192-byte external allocation too large for this process.
I call images like that
BitmapFactory.decodeResource(res, id)
and i put it to array.
I can't scale images.I am using all of them.
I tried that
options.inPurgeable=true;
and it work but the image is loading very slowly.I load a spritesheet with that and when it is loading, i get very very low fps.
What can I do?
I've had this problem too; there's really no solution other than to reduce the number/size of bitmaps that you have loaded at once. Some older Android devices only allocate 16MB to the heap for your whole application, and bitmaps are stored in memory uncompressed once you load them, so it's not hard to exceed 16MB with large backgrounds, etc. (An 854x480, 32-bit bitmap is about 1.6MB uncompressed.)
In my game I was able to get around it by only loading bitmaps that I was going to use in the current level (e.g. I have a single Bitmap object for the background that gets reloaded from resources each time it changes, rather than maintaining multiple Bitmaps in memory. I just maintain an int that tracks which resource I have loaded currently.)
Your sprite sheet is huge, so I think you're right that you'll need to reduce the size of your animations. Alternatively, loading from resources is decently fast, so you might be able to get away with doing something like only loading the animation strip for the character's current direction, and have him pause slightly when he turns while you replace it with the new animation strip. That might get complicated though.
Also, I highly recommend testing your app on the emulator with a VM heap set to 16mb, to make sure you've fixed the problem for all devices. (The emulator usually defaults to 24mb, so it's easy for that to go untested and generate some 1-star reviews after release.)
I am not a game dev however I would like to think I know Android enough.
Loading images of the size is almost certain to throw errors. Why are the images that file size?
There is an example at http://p-xr.com/android-tutorial-how-to-paint-animate-loop-and-remove-a-sprite/. If you notice he has an explosion sprite of only ~200Kb. Even a more detailed image would not take much more file space.
OK some suggestions:
Are you loading all your spritesheets onto a single sheet or is
each spritesheet in a seperate file? If they are all on one I would
split them up.
Lower the resolution of the images, an Android device is portable
and some only have a low resolution screen. For example the HTC
Wildfire has a resolution of 240x320 (LDPI device) and is quite a
common device. You have not stated the image dimensions so we can't be sure if this is practical.
Finally; I am not a game programmer but I found this tutorial (part of the same series) quite enlightening - http://p-xr.com/android-tutorial-2d-canvas-graphics/. I wonder if you are applying a pattern that is not appropriate for Android, however without code I cannot say.
Right something a little off topic but worth noting...
People under estimate the power of the View. While there is a certain amount of logic to using a SurfaceView, the standard View will do quite a lot on its own. A SurfaceView more often than not requires an underlying thread to run (that you will have to setup yourself) in order to make it work. A View however calls onDraw(), which can be utilized in a variety of ways including the postinvalidate() method (see What does postInvalidate() do?).
In any case it might be worth checking out this tutorial http://mindtherobot.com/blog/272/android-custom-ui-making-a-vintage-thermometer/. Personally, it was an excellent example of a custom View and what you can do with them. I rewrote a few sections and made a pocket watch app.