OnMeasure is called 1500+ times

I recently noticed a significant performance issue in my application. I essentially have the following layout ... enter image description here

DESCRIPTION In short, there is ViewPager

one that contains 3 RelativeLayout

as pages. Each page contains a number TextView

s. I recently noticed a lot of lag when I typed in EditText

that has TextWatcher

to execute a quick SQL query for autocomplete. My HTC One M8 stutters and lags when I was typing, but I know this is not a slow request because I was measuring requests taking only about 7ms.

I used profiling, Systrace and regular old Log

debugging and found that every time I typed a character, EditText

about 1700 calls onMeasure

were made to TextView

inside RelativeLayout

A, B, and C. In total, there are only about 15 independent pages on the pages TextView

. I noticed that each onMeasure

is called hundreds of times, not once or twice
as usual.

Question
I don't know why typing text EditText

on page B will cause others TextView

on pages A and C to be "re-measured" as well. More importantly, does anyone know why onMeasure

it gets called so often? And does anyone know of a solution to significantly reduce the number of calls by onMeasure

?

DETAILS This might help: I ​​was actually able to reduce the number of calls onMeasure

to around 900 by removing RelativeLayout

2, which might suggest that call propagation onMeasure

starts outside ViewPager

.

+3


source to share


1 answer


Although I don't have enough information to identify a specific problem, I can tell you in general what is happening:

Calling the root view measure

causes each sub-view to be called measure

, etc. down the tree.

Suppose a view called "current view", after each of its submatrices measures itself, decides that there is not enough room for all the children. He will ask each of them to measure themselves again, suggesting the maximum size. Suppose a view called "Relative Layout B" radically changes its size based on the specified max. Because the change is so large, the "current view" has to query each child again. This loop can easily take a couple more iterations.

When the "current view" decides on its size, it returns to the "View Pager". Suppose the "View Pager" doesn't have three viewing spaces and needs to ask them to re-measure from max. We now have at least 20 calls to TextView onMeasure

. If each of the other views above the ViewPager is repeated multiple times, pretty soon you start seeing big numbers.



The best solution, as you already pointed out, is to decrease the depth of this tree. Alternatively, you can use layout managers which have much simpler measurement algorithms (FrameLayout, LinearLayout)

Nevertheless,

1500. One of these looks does something strange. You should be able to identify it very easily using the TreeView tool in the DDMS package. In eclipse, this is called a TreeView. In Studio, click the Android icon and switch to the hierarchy view perspective. You can also run it from the command line from the SDK tools directory.

Added: If you connect the Hierarchy Viewer to your application while it is running, you will see the entire view tree in one of your panels. Each node in the tree will have three colored gumdrops towards the bottom. The first gumdrop represents the measurement phase. If the gumdrop is green, the measurement phase for that view is fast. If it's yellow, then the node is in the top 50 percentile of nodes in the layout. If it is red, it is the slowest in the layout.

You should be able to follow the yellow before the offending gaze.

+7


source







All Articles