私のアプリケーションでは、ViewのonMeasure()オーバーライドの1つに無限ループがあります。 onMeasureのブレークポイントから始まるソースコードをデバッグすると、ViewRootによって呼び出されるPhoneWindow $ DecorViewのmeasure()(View Hierarchyの最上位クラス)までスタックトレースまでトレースできます。 .performTraversals()。ここからステップオーバーを続けると、最終的にはLooper.loop()クラスのメッセージによってPhoneWindow $ DecorViewのmeasure()が再度呼び出されます。無効化のように、再測定が必要なメッセージがキューに入れられていると思います。
私の質問は、メジャーコールがビューで発生する必要があるトリガーは何ですか?
レイアウト/測定/描画プロセスの私の理解から、これは特定のビューでinvalidate()メソッドが呼び出されたときにのみ発生し、無効化されたビューとすべてのビューのレイアウト/測定/描画パスを実行しますその子。どういうわけか、ビュー階層の一番上のビューが無効になっていると思います。
しかし、私は明示的に無効化の呼び出しごとにブレークポイントを設定しており、無限の方法で無効化を呼び出していません。だからそうだとは思わない。測定パスをトリガーする別の方法はありますか?内部的に何かがこれを引き起こしている可能性がありますか?無限の無効化は何もないと思った後、私は一種のアイデアから外れています。
カスタムビューのメジャーパスをトリガーするには、requestLayout()メソッドを呼び出す必要があります。たとえば、Viewを拡張するカスタムビューを実装し、TextViewのように動作する場合、次のようなsetTextメソッドを記述できます。
/**
* Sets the string value of the view.
* @param text the string to write
*/
public void setText(String text) {
this.text = text;
//calculates the new text width
textWidth = mTextPaint.measureText(text);
//force re-calculating the layout dimension and the redraw of the view
requestLayout();
invalidate();
}
さて、ビューのコンテンツを変更する場合、最終的にinvalidate()を呼び出す必要があります。たとえば、「テキスト1」というテキストを持つTextViewがあります。次に、同じTextViewのテキストを「Text 2」に変更します。ここでも、invalidateが呼び出されます。
そのため、基本的に、ビューで何かが変更されると、多くの場合、無効化メソッドが呼び出され、対応するmeasure()の呼び出しが期待されます。
たとえば、TextViewのソースコードを見てください。 http://www.google.com/codesearch#uX1GffpyOZk/core/Java/Android/widget/TextView.Java&q=TextView%20package:Android&type=cs
無効化呼び出しの数をカウントします。かなりあります。