3

私は、テキストを数千分の 1 秒間表示してから、もう一度空白にする必要がある Android アプリケーションを作成しています。私が今持っているのは、テキストを表示してから Thread.sleep を使用してから、テキストを null に戻すことです。代わりに、ボタンを押すと、アプリが一定時間ハングし、テキストが表示されず、logcat に「xxx フレームがスキップされました。アプリケーションがメイン スレッドで多くの作業を行っている可能性があります」と表示されます。何が起こっているのでしょうか。また、より良い方法はありますか?

4

2 に答える 2

4

ランナブルを使用してみてください。

private Handler mHandler = new Handler();

//code to make text appear...

    mHandler.postDelayed(makeTextDisapear , 3000); // Replace 3000 with the number of milliseconds you want the text to display.

    private Runnable makeTextDisapear = new Runnable() {
            public void run() {
                // code to make text dissapear

                }
            };
于 2012-10-22T02:03:28.967 に答える
2

他の回答が問題の解決に役立ちますが、あなたの質問は、なぜこれが起こっているのかということでもありました:

静的メソッドのいずれかを呼び出すThread.sleep()と、メソッドが呼び出されたスレッドは、指定した時間 (おおまかに) 一時停止状態になります (指定した時間と正確に一致するとは限りません)。

Android では、Ui フレームワークがスレッド セーフになるように設計されていないため、Ui 操作は「メイン」UI スレッドで実行する必要があります。つまり、 a のテキストを設定するときは、メイン スレッドで TextView呼び出す必要があります。メインにメッセージを投稿して、TextView (および親) を再レイアウトして無効にします。近い将来、これらのメッセージが処理され、ビュー階層が更新される予定です。textView.setText(...)setTextLooper

setTextこの作業負荷が大きいため、この作業を直接行うことはありません。また、直接行うと、フレームワークがそのようなリクエストをバッチ処理できなくなります。

次に を呼び出すThread.sleep(...)と、メインの UI スレッドが一時停止状態になりますが、通常、TextView と親の再レイアウトと無効化を実行するのはこのスレッドです。

Android は、新しいフレーム (何かが変更された場合) を 16 ミリ秒未満でレンダリングして、60 fps 以上を維持できるようにしたいと考えています。メイン スレッドが集中的な処理を行っている場合、または 16 ミリ秒を脅かすような長時間 (スリープによって) 一時停止している場合、表示されているエラー メッセージが logcat に投稿されます。

Lollipop では、実際のレンダリングは独自のレンダリング スレッドで実行されますが、メイン スレッドからタイムリーに更新する必要があります。

これを修正する方法については、Jason の回答を参照するか、代わりに、(ハンドラー インスタンスを直接ではなく) ビュー自体に遅延実行可能ファイルを投稿します。

textView.setText("show me!");    
textView.postDelayed(new Runnable() { 
     public void run() { 
         textView.setText(""); 
     }
}, 30);

これが定期的に発生しているRunnable場合は、フィールドとして保持することにより、毎回の割り当てを回避します。

いずれの場合も、匿名の内部クラス ( Runnable) を作成すると、Activity のメモリ リークが発生する可能性がありますが、それは別の話です。

于 2015-05-01T08:23:20.547 に答える