28

以下のコードのように、コンストラクターにカスタムフォントを設定する単純なカスタム TextView があります。

public class MyTextView extends TextView {

    @Inject CustomTypeface customTypeface;

    public MyTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        RoboGuice.injectMembers(context, this);
        setTypeface(customTypeface.getTypeface(context, attrs));
        setPaintFlags(getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
    }
}

Gingerbread から JB 4.2 まで正常に動作します。しかし、Android 4.3 フォンでカスタム テキストビューを表示すると、adb logcat に次のメッセージが殺到します。

10-05 16:09:15.225: WARN/View(9864): requestLayout() improperly called by com.cmp.views.MyTextView{42441b00 V.ED.... ......ID 18,218-456,270 #7f060085 app:id/summary} during layout: running second layout pass
10-05 16:09:15.225: WARN/View(9864): requestLayout() improperly called by com.cmp.views.MyTextView{423753d0 V.ED.... ......ID 26,176-742,278 #7f060085 app:id/summary} during layout: running second layout pass

UI が少し遅くなることに気付きました。4.3 でなぜそれが起こっているのか、何か考えはありますか?

あなたの助けに感謝。

4

5 に答える 5

6

アプリでこのバグが発生する場所を見つけました。これは、提供されたコードでは発生していませんが (コードの他の場所でこれを行った場合に役立つ場合があります)、他の人がこの追跡不可能な問題を修正するのに役立つことを願っています。

私は行を持っていました(もちろん、私が追加したものではありません):

myView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
    @Override
    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
        //this would then make a call to update another view's layout.
    }
});

私のアプリでは、リスナーは必要なかったので、このブロック全体を削除することでこの問題は解決しました。このようなものが必要な場合は、レイアウトが変更された後 (このコールバック内) にリスナーを削除することを忘れないでください。

于 2014-03-28T17:34:22.383 に答える
2

Android ソース を見ると、この問題はもう少し詳しく説明されています。

requestLayout()レイアウト中に呼び出されました。要求元のビューにレイアウト要求フラグが設定されていない場合、問題はありません。一部のリクエストがまだ保留中の場合は、これらのフラグをクリアし、この状況を処理するために完全なリクエスト/測定/レイアウト パスを実行する必要があります。

この問題は Roboguice に関連しているようです。問題 #88を参照してください。推奨される解決策は、@InjectView を使用することです。

ビュー クラス内から @InjectView を使用できるようになりました。ビューにデータを入力した後、Injector.injectMembers() を呼び出すだけです。

public class InjectedView extends FrameLayout {

    @InjectView(R.id.view1) View v;

    public InjectedView(Context context) {
        super(context);
        final View child = new View(context);
        child.setId(R.id.view1);
        addView(child);

        RoboGuice.getInjector(context).injectMembers(this);
    }
}

おそらくRoboGuice.injectMembers(context, this)、 @InjectView アノテーションを使用して View オブジェクトの宣言に移行することを検討する必要があります。

于 2014-02-02T17:56:35.830 に答える