Android experts, I need some help. I'm an Android noob. I have an application where I need to draw a bitmap using canvas from outside the main UI thread. I stumbled onto the SurfaceView class and mocked up a quick demo. I created a seperate bitmap instance and draw into it. When the OnDraw for the surfaceView occurs, I copy this bitmap into the SurfaceView. It works great until the activity ends by, for example, going back to the home screen. At that point, the SurfaceView thread seems to stop, and I seem to lose the bitmap image I was working on. When you return to the app, it starts all over from scratch.
I would like to create the bitmap image using the canvas 2D drawing calls from a thread that is seperate from the main UI thread for performance reasons. I need to get that bitmap into the main user interface once in awhile. And I need the bitmap image to be retained and continue to be drawn into (to keep it current) when the activity is paused or stopped.
Since you must do all drawing in the main UI thread the SurfaceView seems like the only solution. But it doesn't quite work like I hoped either.
I need a background task or thread that NEVER stops running and I need to create a bitmap image there, and I need to get that bitmap into the main user interface once in awhile (say 10 hz updates).
HELP! How do I do this?
Use an asynctask to draw the image onto your ui.
However, the canvas needs to be redrawn when the app is re-opened. If you want to save the bitmap that you created you will need to store it somewhere. I think this can be handled using caching:
view.setDrawingCacheEnabled(true);
Else look into managing the bitmap yourself:
v1.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(v1.getDrawingCache());
Related
I've seen some code on this site that does that but I don't understand how it can work. From what I understand, AsyncTask is only suitable for tasks of only a few seconds and only executed once. For drawing bitmap on a canvas, it has to be redrawn over and over to be displayed on the canvas so I don't see how AsyncTask can work.
Will it be advisable to draw Bitmap on canvas using AsyncTask?
Thanks
You are right, Async tasks are best used for something that is only executed once. As a result, You could possibly use an AsyncTask to decode the bitmap and store it in a variable.
This variable can then by used to render the bitmap in the onDraw()
A SurfaceView might also be more useful for what you need.
i have written a litte app that should display a tacho that gets it data about rpm... over bluetooth. when the data changes i rotate a needle and some other imageViews to display the current values on the screen.
rotate code:
bMapRpm=bMapcanvasBackTacho.copy(bMapcanvasBackTacho.getConfig(), true);
canvasRpm.setBitmap(bMapRpm);
canvasRpm.save();
canvasRpm.rotate((float)Rpmdegree+(float)Rpmcurrentdegree,bMapRpm.getWidth()/2,bMapRpm.getHeight()/2);
canvasRpm.drawBitmap(bMapNadel,0,0,paint);
canvasRpm.restore();
bMapcanvasBackTacho is just a transparent background.
bMapNadel is the bitmap of the needle.
bMapRpm is the bitmap of the canvas to draw on
to update the imageView i allways call:
ivNadel.setImageBitmap(bMapRpm);
i tryed out what slows the app by commenting parts of the code out.
after commenting the setImageBitmap() out the slow down disapeared.
doese someone know how to update the imageView in an other way or whta i could change to get it to work faster?
thx =)
You can do two things:
First, don't call copy() each time you need to update the Bitmap this creates a new Bitmap and is both time and memory consuming.
Second, call invalidate() on the ImageView. This will notify the View that something has changed and it redraws itself without having to update anything else that is happening when you replace the Bitmap completely.
In the end you might even want to create your own View implementation so you can just override onDraw() and perform rotations there.
So I'm working on developing a game for a school project and so far its gone well, but I have been trying to use a bitmap image instead of just using drawColor for the background, but doing so has make the game sluggish, not respond to to Touch Events, and ultimately crash after a while. Here is my code so far for making that background that keeps crashing, I am using the getColor before the drawBitmap as to blank out the previous background, because without that the moving character threads were leaving a "trail" and not being erased after every movement.
canvas.drawColor(Color.BLACK);
canvas.drawBitmap
(BitmapFactory.decodeResource(getResources(),R.drawable.park),0,0,null);
So any more effective method to make a static background image for the thread to move over would be appreciated!
What you are doing is that you are loading your bitmap everytime you're rendering, which is why it runs slow and crashes after a while because of memory constraints. You should load your image once when you initialize everything:
// run once when you start the game
Bitmap background = BitmapFactory.decodeResource(getResources(),R.drawable.park);
In your render code:
canvas.drawBitmap(background);
And don't forget too free the image when you're done with it:
background.recycle();
The reason your application is slowing down is you are keeping too many references to the same bitmap and this is consuming the amount of memory that you have available, you need to release images as you dont need them. There a bunch of videos by Romain Guy on graphics and game graphics. Look on youtube and you'll learn how to handle this problem.
I am trying to construct a SurfaceView by reading in an array and using case switches to build the canvas.
so the question is: can I construct a canvas looping Y, by tracking X. loading bitmaps using BitmapFactory() into the canvas and then using 1 .show() to render the canvas to the screen? or will I need to call the canvas render for each of these (or will that through away the screen every time I do that)?
Not sure what you're getting at, but for one thing avoid using BitmapFactory in onDraw. You don't want to be doing bitmap decoding at the same time as rendering. You should load your bitmaps ahead of time and keep them around in memory for faster drawing later on.
Been working on a custom tile overlay implementation for an android app.
I'm having trouble with threading the image downloads in the background.
Quick overview:
I have a class (MapOverlay) that extends Overlay. The draw method basically calculates the images (bitmaps) needed and the x,y position to draw them on the screen. I then have an AsyncTask that loops through each tiles and download the images if it doesn't exist on the storage card (local caching) then once the AsyncTask has completed I then loop through the images and draw them to the canvas object that is passed into the draw method of the MapOverlay. But the bitmaps are never getting drawn.
I have done some rudimentary debugging by logging the width and the height of the canvas element at the time the AsyncTask completes but it is returning 0 for them so I'm guessing that the canvas object is no longer available to the code running in AsyncTask's onPostExecute() after the draw method has completed
Without the threading I had this working pretty well, except for the "freezing" while panning while the image downloading blocks the UI thread. Now I'm totally suck trying to get threading to work
Have you tried calling postInvalidate() when the AsyncTask done downloading? That way the call in MapView.draw() will get and draw the downloaded overlay (that is if your caching system works).