2017-10-22 18 views
4

私のAndroidの静止画では、ユーザーの30%がレンダリングに時間がかかります。私のアプリはかなり複雑なUIを持っているので、この問題を解決するための基本的なプロジェクトを作った。しかし、それはレイアウトの最も単純なものでさえかなり遅いことが分かります。最も基本的なレイアウトの描画が遅い

レイアウトのAndroidスタジオがテンプレートとして提供することを中心とテキストです:

Timer updateTicks = new Timer(); 
updateTicks.scheduleAtFixedRate(new TimerTask() { 
    @Override 
    public void run() { 
     runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       Random r = new Random(); 
       timerView.setText(String.format("%02d", r.nextInt(60))+":"+ 
            String.format("%02d", r.nextInt(60))); 
      } 
     }); 
    } 
}, 100, 1000); 

<?xml version="1.0" encoding="utf-8"?> 
<android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="slowrenderingtest.pichaipls.com.slowrenderingtest.MainActivity"> 

    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:id="@+id/timerView" 
     android:text="00:00" 
     android:textSize="40dp" 
     app:layout_constraintBottom_toBottomOf="parent" 
     app:layout_constraintLeft_toLeftOf="parent" 
     app:layout_constraintRight_toRightOf="parent" 
     app:layout_constraintTop_toTopOf="parent"/> 

</android.support.constraint.ConstraintLayout> 

レイアウトを使用しての活動は、すべての2番目のテキストを変更するには、(それはタイマーだから)私がGPUプロファイリングをオンにすると、これはいくつかの低速デバイス(明らかにユーザーの30%)で各フレームを描画するのに16msの限界にかなり近づいています。ただ1つのTextView。しかしここにキャッチがあります:最初にアクティビティを実行すると、レンダリング時間は短くなりますが、数秒後にシュートアップします。私が画面に触れ続けると(画面上にコントロールがない)、レンダリング時間は低いままです。これはCPU/GPUが低電力状態になっているためです(レンダリングに時間がかかります)。

私の問題はAndroidのバイタルです。レンダリング時間が遅いという警告が表示されています(レンダリングが遅いセッションの5%を超えると警告が表示されると思いますが)これをどのように高速化できるかはわかりません。そして私はそれが私のアプリのランク付けに影響を与えるかもしれないと心配していますが、この本当に単純な例でさえ、あまりにも多くのAndroidユーザーが遅いデバイスを持っています。

これについて何かできますか?

+0

CPUプロファイリングを実行して、どのメソッドがより多くの時間を取っているかを調べることができますか?それは 'rです。UIスレッドであまり使わないべきnextInt() 'は –

+0

です。いいえ、' r.nextInt() 'とは関係ありません。私はちょうど増加する数字を表示する場合、問題は同じです。実際には、CPUに負担をかけると描画が高速になるようです。その代わりに乱数を生成するのではなく、その数の階乗も計算すれば、GPUの更新が遅いという問題は解決されますが、恐ろしく非効率的です。 – TimSim

答えて

3

私たちは同じ問題を抱えています。よく掘り下げた後、CPUが空いていると思われますか?

私たちの場合は似ています。 Handlerを使用して毎秒TextViewのテキストを更新するRunnableがあります。 TextViewはRecyclerView内のアイテムにあります。興味深いことに、ページをスクロールしたり、アニメーションが進行したり、アプリと対話しているとき(基本的にはティッキング以外の何か他のもの)、16msのマークを打つことはありません。しかし、デバイスをアイドル状態にして、各フレームが30〜50 msの間にあるようにしてください。

同様の状況でSOに記載されているdifferent solutionsを試しました。 Viewの幅をwrap_contentからmatch_parentに変更する。この問題を助けなかった。 1000ms間隔を500,200,100,50,20,16,10に変更しようとしましたが、16/10ms(CPUは常に動作していますか?

CPUスロットリングに関するthis articleが見つかりました。おそらく、CPUがアイドル状態のとき、フレームを描画するのにもう少し時間がかかりますか?

Android StudioでCPUモニタを見ると、何も起こっていなくてもCPUがアイドル状態になることがわかります。 (インタラクションがある場合とNexus 5を使用している場合があります)。 enter image description here

しかし、画面上のプロファイルGPUレンダリングバーとはかなり違って見えるGPUモニタを見ると、フレームは実際には16msのマークを横切っていません!どちらのGPUモニタリングが正しいか分かりません。 (大きな黄色のものは相互作用があるときです)。 enter image description here

+1

はい、テキストビューが50msごとに更新されるアップデートを提出しました。私はそれがバイタルを改善するかどうかを見るでしょう。もしそうであれば、Googleの時には息をのむような無能のもう一つの例になるだろう。 – TimSim

+0

うん、1秒に60回タイマーを更新すると問題が解決します。現在、携帯電話を低電力状態にする代わりに、Googleの「悪い動作」の基準を満たすために絶えず動作しています。 – TimSim

+0

@TimSim私たちはこのアプローチを試みましたが、バッテリホッグなので、これは標準的なアプローチではなく、「悪い挙動」のメトリックを修正することができます。そこで私たちは今のところそれを残すことに決めました。驚いたことに、コードが基本的に同じでも、Playストアでフリーズフレームの問題が表示されなくなりました。おそらく、彼らはこの測定基準をどのように計算するかを変えたでしょう。 –

0

テキストビューをmatch_parentにするようにしてください...毎秒テキストを変更すると、TextViewは毎回サイズを計算する必要があります。あなたは結果に驚かれるでしょう...

+0

すでに試してみましたが、違いはありません。 – TimSim

関連する問題