60

My answer to this question was just accepted but I started to wonder when exactly one needs to invalidate() a View and when it is not necessary?

After a bit of thinking I came to realization that it should work more or less like this:

  • actual drawing of "everything" occurs after onResume()
  • in "free" time parts of the screen can be redrawn but only those that were invalidated (and everything underneath)

Therefore, it would seem, if I change something after onResume() (e.g. as a response to a button click, I should invalidate() the changed View).

However, from what scana in this question says, it must be more complex then that and it depends somethimes on what method one uses.

E.g. on whether one uses

lastClicked.setImageBitmap();

or

lastClicked.setImageResource();

So, when it's necessary to execute invalidate() on a View and how does it really work ?

Community
  • 1
  • 1
mjaskowski
  • 1,479
  • 1
  • 12
  • 16

4 Answers4

103

(Do consider accepting some answers)

Generally, invalidate() means 'redraw on screen' and results to a call of the view's onDraw() method. So if something changes and it needs to be reflected on screen, you need to call invalidate(). However, for built-in widgets you rarely, if ever, need to call it yourself. When you change the state of a widget, internal code will call invalidate() as necessary and your change will be reflected on screen. For example, if you call TextView.setText(), after doing a lot of internal processing (will the text fit on screen, does it need to be ellipsised, etc.), TextView will call invalidate() before setText() returns. Similarly for other widgets.

If you implement a custom view, you will need to call invalidate() whenever the backing model changes and you need to redraw your view. It can also be used to create simple animations, where you change state, then call invalidate(), change state again, etc.

Nikolay Elenkov
  • 52,576
  • 10
  • 84
  • 84
  • 2
    to complete this answer i'd say that lots of times is important to check the code of the various method you might use on a widget to understand when there is an invalidate call and implement a layout in order to minimize them. for instance if you have a complex layout a single TextView with wrap_content will always invalide() all your layout a the end of every call to setText(), on the other end if you manage to get a fixed dimension only the text inside the view will be changed with result of a much more fluid GUI. – Mario Lenci Sep 24 '12 at 09:35
31

Usually, the system handles resizing, hiding, showing and a ton of other things for your widgets automatically but it sometimes has issues if the underlying buffer for drawn pixels or backing data has changed or is stale (you swap the image resource on a View or the raw dataset changes). This occurs because there is no way that the OS can know that the data changed in the specific manner that it did.

In these cases where you are dealing with drawing, you have to tell the system that its underlying data is not in a good state with Widget.invalidate() and the re-drawing gets queued on the main thread just as you mentioned. Depending on the system implementation and Android version what is tracked for changes by the system varies but what I normally do is assume that system resources (byte arrays, char arrays, resource indexes, manual drawing on the context) are not tracked and need an invalidate and everything else will be handled by the system.

Srdjan Grubor
  • 2,605
  • 15
  • 17
0

Please remember that drawing on the screen is frequent process, whenever you update a view, that change should be propogated and redrawn to notify such change right. invalidate() is a trigger method,that signals force reDrawing of any view you wish to show changes for.

Remario
  • 3,813
  • 2
  • 18
  • 25
-2

I had this problem when I wanted to draw a textPaint! My code was

    canvas.drawPaint(textPaintNumber)
    canvas.drawText("MyText", 30F, 63F, textPaintNumber)

I cleared the first lint and the problem was solved

    canvas.drawText("MyText", 30F, 63F, textPaintNumber)
Maryam Azhdari
  • 1,161
  • 11
  • 8