0

I am having problems redrawing the view in a painting app. When the touch ends, I call touch_up() to make the path, invalidate() to draw it, and storeView() to push the current view on the stack. However, the view is not redrawn at all (until the next touch, giving it a twitchy effect). If I delete the call to storeView() it does redraw right away.

I understand from here that the issue is invalidate() does not necessarily happen immediately and I think I need to create a new thread or handler to wait for it. Despite reading the dev pages, I don't fully understand how to implement that.

Is that really what I need to do? How can I make storeView() wait until the view has been redrawn? I've fought with this a while, an answer would make my day. Thanks!

Here's what I currently do.

Action_up:

case MotionEvent.ACTION_UP:
    touch_up();
    invalidate();
    storeView();
    break;

Touch_up:

private void touch_up() {
    mPath.lineTo(mX, mY);
    // commit the path to our offscreen
    mCanvas.drawPath(mPath, mPaint);
    // kill this so we don't double draw
    mPath.reset();
}

storeView:

public void storeView(){
    historyCount++;
    if(historyCount > historySize) historyCount = 6;    //We don't want more than 6
    history.add(Bitmap.createBitmap(myView.getDrawingCache()),historyCount);
}
Community
  • 1
  • 1
jarvisteve
  • 926
  • 8
  • 14

1 Answers1

1

When the touch ends, I call touch_up() to make the path, invalidate() to draw it, and storeView() to push the current view on the stack.

Why is storeView() holding an entire bitmap? Why aren't you using storing commands that you can replay (and possibly reverse)? You are taking up gobs and gobs of RAM this way.

I understand from here that the issue is invalidate() does not necessarily happen immediately

Correct.

and I think I need to create a new thread or handler to wait for it.

No, if you are going to stick with your save-the-whole-bitmap implementation, you need to make sure that storeView() is called after invalidate() completes. Wrapping the call to storeView() in a Runnable and scheduling that Runnable via a call to post() on myView should suffice.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Thanks, I'll try that. I know the bitmaps take up relatively a lot of RAM, but I'm doing that way because storing the paths alone won't handle, for example, importing a picture. I limit the size of the stack so it doesn't get out of control. – jarvisteve Jul 22 '11 at 18:15
  • Your general disapproval inspired me to set things up differently. I think with a kind of linked list I can store all the various commands/imports needed. I appreciate your help. – jarvisteve Jul 22 '11 at 18:57
  • @sajarvis: It's more that we see developers run out of heap space time and again with bitmaps, so anything you can do to reduce the number of bitmaps (particularly big ones, like with a painting app), the better luck you will tend to have. – CommonsWare Jul 22 '11 at 19:01
  • Since yesterday I've hit a road block with each method. I implemented a stack of paths and then restored all but the last on undo. I cannot get the paths from the history to actually draw though (Tried the same with saving states of the Canvas, thinking that'd be the way to go since it holds all the draw commands). And the save the whole bitmap way doesn't actually save the current drawingcache. It stores the initial version each time, like it can't see changes from the runnable. Any ideas? I appreciate your patience, I took this on because graphics has never been my strong suit. – jarvisteve Jul 23 '11 at 21:51
  • @sajarvis: Sorry, you are wandering outside my area of expertise. – CommonsWare Jul 23 '11 at 21:58