1アプリの起動方法
アプリの起動は、コールドスタート、ウォームスタート、ホットスタートに分類できます。その中でも、コールドスタートはアプリの起動に最も長い起動時間ですが、本日はコールドスタートの起動速度の最適化についても説明します。
1.1コールドスタート
アプリの起動時、バックグラウンドでアプリに対応するプロセスはありません。たとえば、電話の起動後に初めてアプリを実行したり、システムメモリが不足しているため、Killがドロップされた後にアプリプロセスが再起動したり、ユーザーがアプリプロセスをアクティブに終了したりします。この状況では、システムがアプリに割り当てる新しいプロセスを作成する必要があり、アプリは初期化プロセスを実行する必要があります。コールドスタートは、アプリの起動を開始する最も長い時間です。
1.2ウォームスタート
アプリプロセスは有効ですが、現在のアクティビティは存在しません。たとえば、何らかの理由でアプリがバックグラウンドに切り替わり、メモリが不足しているためにアクティビティがリサイクルされる場合があります。現時点では、アプリを起動してプロセスを再作成する必要はありませんが、アクティビティはオブジェクトを再作成する必要があります。
1.3ホットスタート
アプリプロセスは有効であり、現在のアクティビティオブジェクトはまだメモリに存在し、リサイクルされません。アクティビティと初期化を再作成する必要はありません。たとえば、ホームボタンまたはタスクボタンを押して、アプリを終了して他のことを実行し、すぐにアプリの状況にすばやく戻ります。
2最適化のアイデア
前の記事「Androidアプリケーションの起動の詳細な説明(1)AndroidシステムとAndroidアプリケーションの起動プロセス」で、startActivityからActivityThread.main()までのアプリの起動がシステムの動作であり、介入できないことを学びました、そしてアプリを作成するプロセスの後、記事「Androidアプリケーションの起動の詳細な説明(2)アプリケーションとアクティビティの起動プロセス」のいくつかのソースコード分析は、おそらくプロセスがアプリケーションオブジェクトと最初のアクティビティオブジェクトを作成することであると理解できます。対応する初期化作業とコールバックライフサイクルメソッドのプロセスを実行します。アクティビティが起動すると、ウィンドウを作成し、ビューをロードして、最初の描画を完了します。アプリが初めて描画を終了すると、代わりに白黒の背景がカットされ、ユーザーとのインターフェースが表示されます。
したがって、起動速度を最適化する必要があります。開始点は、アクティビティが作成された後、アプリケーションの初期化プロセス、表示ビュープロセス、およびビュー描画プロセスに配置されます。これらのプロセスでは、集中的で重いイベントを避けてください。つまり、アプリケーションのattachBaseContext、onCreate、ActivityのonCreate、onStart、onResume、インターフェイスレイアウトを最適化する必要があります。
3最適化戦略
3.1非同期読み込み/遅延読み込み
一部のデータのプリロードは、可能な限り非同期スレッドに配置する必要があります。データがロードされた後、必要に応じて、コールバックコールバックを通じて通知されます。
読み込みの遅延とは、メインポイントが最初に読み込まれ、postDelayedを使用して最初に不要な残りのポイントをポストロードして、ユーザーが主要な機能をすばやく確認できるようにすることを意味します。
一般的なシナリオは次のとおりです。
1 サードパーティSDKの初期化
多くの場合、サードパーティのSDKをアプリケーションのAttachBaseContextまたはonCreateにロードします。これは、アプリケーションの起動時間を増加させる原因でもあるため、アプリケーションのAttachBaseContextまたはonCreateでの同期初期化操作を回避するようにしてください。より良い解決策は、最初にSDKが必要かどうかを最初に分析し、必要でない場合は遅延して、または実際に使用するときにロードすることです。
2 MultDex 下請け状況
今日のますます複雑化するApp機能では、MultiDexはほぼ避けられず、5.0より前の携帯電話の起動速度は単なる悪夢です。起動速度を最適化するために、multiDexKeepProguard属性またはmultiDexKeepFile属性を使用して、Gradleスクリプトで外注を構成するときに、指定されたクラスがメインdexファイルに留まるように構成できます。 MultiDex.install(this);を非同期スレッドに配置して実行することを検討してください。ただし、classes2.dexのクラスが事前に呼び出されないように、ロードが完了する前に処理する必要があります。MultiDexのMultiDexKeepProguard属性またはmultiDexKeepFile属性の使用については、前の記事「Android Gradleの使用の詳細な説明(6)65535メソッドの制限を解決する方法」を参照してください。
3 ViewStubを使用してオンデマンドでインターフェイスをロードします
一部のビューは、常にインターフェースに表示されるとは限らず、特定の条件下でユーザーにのみ表示される場合があります。誤った要求のあるビューと同様に、通常のプロセスではまったく表示されません。つまり、それを手放す必要はありません。ロード。したがって、このシナリオでは、ViewStubを使用して処理できます。ViewStubは非常に軽量で、幅と高さが0で、レイアウトと描画プロセス自体には関与しません。つまり、必要なレイアウトファイルをオンデマンドでロードします。
4 最初のフレームが表示された後にロジックを実行します
最初の画面のアクティビティはできるだけ簡略化するか、最初のフレームが描画された後にコードなどの処理を開始する必要があります。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 第一帧显示后执行
getWindow().getDecorView().post(new Runnable() {
@Override
public void run() {
mHandle().post(...);
}
});
}
}
ここで説明すると、DecoViewはViewから継承するため、getDecorView()はルートビューDecorViewオブジェクトを返します。したがって、ビューがonResumeに追加されるため、ここのpostメソッドはViewのPostメソッドに対して呼び出されます。ウィンドウ。したがって、ここでのPostメソッドは、RunnableをHandlerActionオブジェクトにカプセル化し、それをArrayListに格納します。executeActionsメソッドに対して実行されると(executeActionsメソッドは、performTraversalsメソッドで実行され、Viewメジャー/レイアウト/描画プロセス、各フレーム描画がperformTraversalsメソッドによって実行されると、ここにHandlerActionがあり、次にexecuteActionsメソッドを通じて渡されたHandlerオブジェクトが再投稿されます。したがって、このPostの実行可能なオブジェクトは、最初のperformTraversalsメソッドが実行されたときに、MainLooperのMessageQueueに最終的に追加されました。
3.2簡略化されたレイアウト
レイアウトの最適化に関しては、前回の記事「Andorid Performance Optimization(1)How to Optimize the Memory for the App」で「インターフェイスレイアウトの最適化」をすでに紹介していますので、ここでは繰り返しません。
3.3白黒画面を排除する
画面が白黒になるのは、実際には、アクティビティが開始されると、ウィンドウの背景がsetContentViewの前に読み込まれるためです。システムは、デフォルトでウィンドウの背景を白または黒に設定します。アプリの起動が遅すぎると、白黒の画面が表示されます。したがって、この場合、白黒の画面を削除したい場合は、アプリの起動時に軽量のスプラッシュページを追加できます。白黒画面をなくすことは、速度が最適化されたソリューションではありませんが、ユーザーエクスペリエンスを向上させることができます。
4起動速度の評価方法
4.1表示時間
Android 4.4バージョンから、Logcatは各アクティビティがインターフェースに表示されるまでにかかる時間を出力します。この方法は、プログラムの開始時間を測定するのにより適しています。示されているように:
4.2 startMethodTracing()およびstopMethodTracing()を使用する
次のように、生成されたトレースファイルを介してプロセス内の各メソッドの時間のかかる状況を分析するには、時間のかかるコードセグメントにstartMethodTracing startおよびstopMethodTracing endを追加するだけです。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Debug.startMethodTracing("test");
test();
test2();
Debug.stopMethodTracing();
}
private void test() {
try {
Thread.sleep(4);
} catch ( Exception ex) {
ex.printStackTrace();
}
}
private void test2() {
try {
Thread.sleep(3);
} catch ( Exception ex) {
ex.printStackTrace();
}
}
}
このようにして、プログラムの実行後、test / traceファイルがAndroid / data / appパッケージ名/ filesディレクトリに生成されます。AndroidStudioを介してトレースファイルを開き、次のようにコードプロセスの各メソッドで使用される時間を分析します図:
4.3 adbコマンドによるアプリの計算時間の開始
adbコマンドを使用します:adb shell am start -W packageName / packageName.activity、アプリの指定したアクティビティを開始でき、次のような起動時間を表示できます。
WaitTimeは、前のアプリケーションアクティビティの一時停止の時間と新しいアプリケーションの起動の時間を含む、費やされた合計時間を表します。
ThisTimeは、一連のアクティビティを開始する最後のアクティビティの起動時間を表します。
TotalTimeは、新しいプロセスの開始やアクティビティの開始など、新しいアプリケーションの開始に費やされた時間を表しますが、前のアプリケーションのアクティビティの一時停止で費やされた時間は含まれません。
Android 5.0より前のスマートフォンには、WaitTimeの値はありません。通常、必要なのはTotalTimeだけです。この時間は、アプリケーション自体が開始するために費やした時間です。