web-dev-qa-db-ja.com

アプリケーションがそのメインスレッドでやり過ぎている可能性があります。

私はAndroid SDK/API環境に不慣れです。私が初めてプロット/チャートを描こうとしているのです。私は3種類の無料のライブラリを使用してエミュレータで異なる種類のサンプルコードを実行しようとしましたが、レイアウト画面に何も表示されません。 logcatは次のメッセージを繰り返しています。

 W/Trace(1378):nativeGetEnabledTagsからの予期しない値:0 
 I/Choreographer(1378):55フレームをスキップしました。アプリケーションがそのメインスレッドでやり過ぎている可能性があります。 

ライセンスライブラリの評価版に関連するサンプルコードを実行したとき、問題は解決せず、チャートは機能しました。

317
user2038135

から取得:Android UI:スキップされたフレームの修正

Androidアプリケーションの開発を開始した人は誰でもlogcatでこのメッセージを見ることができます。 "Choreographer(abc):Skipped xx frame! それで、実際に何を意味するのか、なぜ気にする必要があるのか​​、どうやって解決するのか。

これは、コードの処理に時間がかかり、そのためにフレームがスキップされることを意味します。おそらく、アプリケーションの中心で行われている重い処理、DBアクセス、またはスレッドを引き起こす他の何かが原因です。しばらく停止します。詳細な説明は次のとおりです。

Choreographerを使用すると、アプリは自分自身をvsyncに接続し、適切にタイミングを調整してパフォーマンスを向上させることができます。

Androidビューアニメーションは、同じ目的でChoreographerを内部的に使用します。つまり、アニメーションのタイミングを適切に調整し、パフォーマンスを改善する可能性があります。

Choreographerにはすべてのvsyncイベントが通知されるため、Choreographer.post * APIによって渡されたRunnableの1つが1フレームの時間で終了せず、フレームがスキップされるかどうかを確認できます。

私の理解では、Choreographerはフレームのスキップのみを検出できます。これがなぜ起こるのかを知る方法はありません。

「アプリケーションはメインスレッドで作業をしすぎている可能性があります。」というメッセージは誤解を招く可能性があります。

source:LogcatのChoreographerメッセージの意味

心配する必要がある理由

このメッセージがAndroidエミュレーターにポップアップ表示され、スキップされるフレームの数がかなり少ない(<100)場合、エミュレーターが遅いという安全な賭けをすることができます。これはほとんどの場合に発生します。しかし、フレーム数がスキップされ、300以上のオーダーの場合、コードに重大な問題が発生する可能性があります。 Androidデバイスは、iosやWindowsデバイスとは異なり、膨大な数のハードウェアで提供されます。 RAMとCPUはさまざまであり、すべてのデバイスで適切なパフォーマンスとユーザーエクスペリエンスが必要な場合は、この問題を修正する必要があります。フレームがスキップされると、UIが遅くて遅延しますが、これはユーザーエクスペリエンスとしては望ましくありません。

修正方法

これを修正するには、長時間の処理があるノード、または発生する可能性のあるノードを識別する必要があります。最良の方法は、メインUIスレッドとは別のスレッドでどれだけ小さくても大きくても、すべての処理を実行することです。 SQLiteデータベースからデータにアクセスするか、筋金入りの数学を実行するか、単に配列をソートするだけです–別のスレッドで実行してください

ここでキャッチがあります。これらの操作を行うための新しいスレッドを作成し、アプリケーションを実行すると、「ビュー階層を作成した元のスレッドのみがそのビューにアクセスできます」とクラッシュします。 AndroidのUIはメインスレッドまたはUIスレッドのみによって変更できるという事実を知っておく必要があります。これを試みる他のスレッドは、このエラーで失敗してクラッシュします。実行する必要があるのは、runOnUiThread内で新しいRunnableを作成することです。このRunnable内で、UIに関連するすべての操作を行う必要があります。例を見つけてください here

メインスレッドからのデータを処理するためのThreadとRunnableがありますが、他に何がありますか? AndroidにはAsyncTaskがあり、UIスレッドで長時間のプロセスを実行できます。これは、アプリケーションがデータ駆動型またはWeb API駆動型である場合、またはCanvasを使用して構築するような複雑なUIを使用する場合に最も役立ちます。 AsyncTaskの機能は、バックグラウンドで処理を実行できることです。処理が完了すると、遅れることなくUIで必要なアクションを実行できます。これは、AsyncTaskがActivityのUIスレッドから派生するために可能です。AsyncTaskを介してUIで行う操作はすべて、メインUIスレッドとは異なるスレッドであり、ユーザーの操作に支障はありません。

ですから、これはスムーズなAndroidアプリケーションを作成するために知っておく必要があることです。

442
Jorgesys

他の人が上で答えたように、 "55フレームスキップしました!"アプリケーションに多少の処理がかかることを意味します。

私の場合、私のアプリケーションには大きなプロセスはありません。私はダブルとトリプルですべてをチェックし、少し重いと思うプロセスを削除しました。

スケルトンだけが残るまで、Fragments、Activities、Librariesを削除しました。しかしそれでも問題は解決しませんでした。私はリソースをチェックすることにしました、そして私がそれらのリソースのサイズをチェックするのを忘れていたので私が使ういくつかのアイコンと背景がかなり大きいのを見つけました。

だから、私の提案は上記の答えのどれもが助けにならないなら、あなたはあなたのリソースファイルのサイズもチェックすることができる。

205
Sithu

私も同じ問題を抱えていました。
私がドロアブルに入っていた背景画像を使っていたのですが、その特定の画像はおよそ130kBで、私のAndroidアプリのスプラッシュスクリーンとホームページの間に使われていました。

解決策 - 私はただその特定の画像をdrawablesからdrawables-xxxフォルダーに移し、バックグラウンドで占有されていた多くのメモリを解放することができ、スキップフレームはもうスキップしませんでした。

更新 背景ドロアブルファイルを保存するために 'nodp'ドロアブルリソースフォルダを使用する。
密度修飾されたdrawableフォルダまたはdrawable-nodpiが優先されますか?

56
Prakhar1001

UIスレッドの遅延のもう1つの一般的な原因は、SharedPreferencesアクセスです。初めてPreferenceManager.getSharedPreferencesなどのメソッドを呼び出すと、関連付けられている.xmlファイルがすぐに読み込まれ、同じスレッド内で 解析されます

この問題に対処するための良い方法の1つは、バックグラウンドスレッドから最初のSharedPreferenceの読み込みをできるだけ早く開始することです(例:ApplicationクラスのonCreateから)。このようにして、あなたがそれを使用したいと思う時までに、嗜好オブジェクトはすでに構築されているかもしれません。

残念ながら、起動の初期段階で初期設定ファイルを読み込むことが必要な場合があります(初期のActivityやアプリケーション自体など)。そのような場合、MessageQueue.IdleHandlerを使用することによってUIの機能停止を回避することは依然として可能です。メインスレッドで実行する必要がある他のすべての操作を行い、アクティビティが完全に描画されたら、IdleHandlerをインストールしてコードを実行します。そのRunnableでは、あまりにも多くの描画操作を遅らせたりChoreographerを不幸にしたりすることなくSharedPreferencesにアクセスできるはずです。

17
user1643723

アプリのパフォーマンスを向上させるために、次の戦略を使用してください。

  • 可能であればマルチスレッドプログラミングを使用してください。スマートフォンにコアが1つあっても、パフォーマンス上の利点は非常に大きくなります(プロセッサに2つ以上ある場合、スレッドは異なるコアで実行できます)。アプリのロジックをUIから分離すると便利です。 Javaスレッド、AsyncTaskまたはIntentServiceを使用してください。 これをチェックして
  • Android開発Webサイトのその他のパフォーマンスに関するヒントを読んで従ってください。 ここでチェックしてください
15
MigDus

私は専門家ではありませんが、自分のAndroidアプリケーションからWebサーバーにデータを送信したいときにこのデバッグメッセージを受け取りました。 AsyncTaskクラスを使用してバックグラウンドでデータ転送を行いましたが、サーバーから結果データを取得するには、UIを同期させるAsyncTaskクラスのget()メソッドを使用しました。だから私のアドバイスはあなたのアプリが別のスレッドですべてのネットワーク指向のタスクを実行するようにすることです。

7
saba

私は同じ問題を抱えていました。 Android EmulatorはAndroid <6.0で完全に動作しました。私がエミュレータNexus 5(Android 6.0)を使用したとき、アプリはログのI/Choreographer: Skipped framesで非常に遅く動きました。

そこで、私はこの問題を解決するために、マニフェストファイルのhardwareAcceleratedオプションをtrueに変更しました。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
    package="com.example.myapplication">

    <application Android:hardwareAccelerated="true">
        ...
    </application>
</manifest>
6
phen0menon

私は同じ問題を抱えていました。私の場合は、2つの相対レイアウトを入れ子にしました。 RelativeLayoutは常に2小節パスを実行する必要があります。 RelativeLayoutsを入れ子にすると、指数測定アルゴリズムが得られます。

5
Radoslav

画像を最適化する... 100KBを超える画像を使用しないでください。画像の読み込みにはCPUの負荷がかかりすぎ、アプリケーションがハングします。

4
HarshitG

私は同じ問題を抱えていました。私が他のコンピュータでコードを実行したとき、それはうまくいった。しかし私の言うところでは、「アプリケーションはそのメインスレッドでやり過ぎている可能性があります」と表示されていました。

Android Studioを再起動して問題を解決しました[ファイル - >無効化されたキャッシュ/再起動 - > [無効化して再起動]をクリックします]。

1
sonida

最初に警告を読みます。それはメインスレッドにより多くの負荷をかけます。だからあなたがしなければならないのはただスレッドの中でもっと仕事をして関数を実行することです。

0
Credoz

これは通常、メインスレッドで長いプロセスを実行しているときに起こります。 200未満のフレームをスキップしても構いません。ただし、200を超えるフレームをスキップすると、アプリケーションのUIが遅くなる可能性があります。できることは、ワーカースレッドと呼ばれる新しいスレッドでこれらのプロセスを実行し、その後、メインスレッドと通信して結果を表示することです。ほとんどの場合AsyncTaskとRunOnUiThreadは問題を解決することができます...

0
Hossein Karami

私のアプリにも同じ問題がありました。しかし、それはカードのリストとその上にテキストを表示する以外のことをしていませんでした。バックグラウンドで実行されているものはありません。しかし、調査の結果、カードの背景用に設定された画像が、たとえそれが小さいとしても(350kb)これを引き起こしていることがわかりました。それから私は http://romannurik.github.io/AndroidAssetStudio/index.html を使って9patch画像に画像を変換しました。
これは私にとって役に立ちました。

0
naamadheya

この問題について多くの研究開発を行った後、私は解決策を得ました、

私の場合は、2秒ごとに実行されるServiceを使用していますが、runonUITスレッドを使用すると、問題は発生したがまったく発生していなかったと思います。私が見つけた次の問題は私が5月のAppで大きいImageを使っているということです、そしてそれは問題です。

画像を削除して新しい画像を設定しました。

結論: - あなたのコードを見れば、あなたが使っている生のファイルが大きいということです。

0
Hector Morris