Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Am I invalidating the entire screen on every call?

I am new to Android Development and reading the book Hello Android. It uses a Sudoku example, and the code that I am referring to is here.

In this , onTouchScreen, it calls select method, that calls invalidate twice. The question is that, on invalidating is the onDraw method called right after that? So will in this case, inside my select method, it will do

  1. invalidate
  2. call onDraw
  3. Do some stuff
  4. invalidate
  5. call onDraw

Is this how it will happen, also, will the entire screen be regenerated? All the numbers and hints etc., because from the book the author says

In an earlier version of this example, I invalidated the entire screen whenever the cursor was moved. Thus, on every key press, the whole puzzle had to be redrawn. This caused it to lag noticeably. Switching the code to invalidate only the smallest rectangles that changed made it run much faster.

What exactly is he trying to say here?

Added Info

I added some logs in the onDraw method, some at the starting, some in the for loop. Whenever I touched a new rectangle, all the logs were called. Doesnt that mean that the entire screen is geting repopulated, since all the code in onDraw is reexecuted?

like image 989
Kraken Avatar asked Jan 09 '14 17:01

Kraken


People also ask

What does invalidate View mean?

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.

What is the purpose to call the function invalidate?

To "invalidate a view" means that any data that may already be drawn is no longer valid. The view of the data is invalid, hence invalidate() to mark it as such. It's less that the function is making it invalid so much as it is already invalid, but no-one except the caller to invalidate() knows that yet.


1 Answers

Kraken

Q: But what about the logs, surely if my loops are getting executed it means that all the canvas.draw will be getting executed too?
A: Yes, the whole drawing will be executed in your sample code. You have to optimize the rendering process by yourself, in onDraw method.

Q: How does the system know, what piece of code will "only" redraw the dirty area?
A: Canvas::getClipBounds will give you a dirty rect, which you should draw something on.
Inside your for loop in onDraw, compare the dirty rect with the rect which you want to draw. Then do continue if they do not intersect.

But remember, if you have several area set to dirty, the returned rect will be a union of all dirty areas.
Please see the following two questions below:
Getting the dirty region inside draw()
Android: invalidate(dirty)

Hope this will help you.

==========================

The author is right. But this still can be optimized.

Calling invalidate(Rect) will automatically set a clip area for the canvas. (That's why canvas.getClipBounds() can return that area).
Then, during onDraw(), anything drawing out of the clip area, will be ignored. They do not appear on the screen, so it REALLY reduce the time of drawing.
But ignoring them still costs overhead. Therefore, for graphical intensive app, onDraw() could be better optimized if you exclude them in advance.

You can find a great example for optimizing onDraw() in android's KeyboardView, which provide the view of your android's input method. http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/1.5_r4/android/inputmethodservice/KeyboardView.java

like image 155
Zhenghong Wang Avatar answered Sep 21 '22 04:09

Zhenghong Wang