Androidシステムソース読解(18):Androidアプリケーションの表示
Androidシステムソース読解(18):Androidアプリケーションの表示
1.Activity Management Serviceの起動
前述の14章では、Systemプロセスが開始されると、システムの基本的なサービスがいくつか起動されます.起動時にActivityManagerServiceとPackageManagerServiceがあります.システムサーバでActivity Management Serviceを次のように起動します.
frameworks/base/services/java/com/android/server/SystemServer.java :
startServiceとは、Activity Management ServiceのインスタンスオブジェクトmActivity Management Serviceを作成し、Activity Management Serviceのlooperスレッドを起動することです.SystemServerが基本サービスを開始すると、mActivityManagerServiceのsystemReady関数が呼び出され、HomeActivityが起動します.
2.ホームActivityの起動
SystemServerのメインスレッドで現在呼び出されているsystemReady関数.この関数は、次にstartHomeActivity Locked関数を呼び出してHomeActivityを起動します.具体的には、次のようになります.
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java :
ここはmStackSupervisorに渡しました.startHomeActivity関数を使用してHomeActivityを起動すると、startActivity Locked関数が呼び出されます.ここでは,2章で一般アプリケーションのactivityを起動する手順を繰り返し,これ以上述べることはない.ここで、LauncherのManifestにはandroidのタイプが示されている.intent.category.ホーム、だから起動したのはLaucherアプリです.
3.Launcher展示応用
次に、LauncherのonCreate関数から始めます.コードの一部は次のとおりです.
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java :
ここでmModelは、アプリケーション情報のロードを担当するLauncherModelオブジェクトです.リロードされたstartLoader関数:
すべてのインストールされたアプリケーション情報をロードするのは比較的時間がかかるプロセスであるため、非同期スレッドに渡して処理する必要があります.ここではまずロードタスクmLoaderTaskを作成し、sWorkerThreadに渡して処理します.sWorkerThreadはHandlerThreadであり、HandlerThreadは独立したスレッドであり、独自のlooperを持っていることを知っています.mLoaderTaskロードタスクは1回で完了しますが、なぜHandlerThreadで他のタスクを待つ必要があるのでしょうか.デスクトップアプリケーションは動的に追加および削除できるため、アプリケーションのロードは頻繁である可能性があります.ここでHandlerThreadを使用すると、ロードスレッドの重複作成を回避できます.
次はLoaderTaskを見てみましょう.run関数で具体的にどのようなタスクをしましたか.
packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.java :
WorkSpaceはAndroidデスクトップの分割画面で、各分割画面にはいくつかのアプリケーションがあります.ワークスペースをロードしてから、アプリケーションをロードするとユーザーの心理的な予想に合いますか?関数loadAndBindAllAppsは、アプリケーションがロードされたかどうかを判断し、情報がロードされている場合は、appをデスクトップに直接表示すればよい.ない場合は、次のような関数loadAllAppsを呼び出す必要があります.
packages/apps/Launcher3/src/com/android/luancher3/LauncherModel.java :
mLauncherApps.getActivity Listがapp情報を取得する方法は、PackageManagerに要求を送信することによって実現される.次にLauncherメインスレッドに戻り、アプリケーションアイコンの表示を開始します.まず、このコールバック関数を見てみましょう.
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java :
mAppsViewはviewのコンテナであり、AlphabeticalAppsListリストを維持し、アプリケーションの情報を保存します.新しいアプリケーション情報を追加すると、ホーム上のアプリケーションが更新されます.ホーム上のアイコンがクリックされると、アプリケーションの起動がトリガーされます.
1.Activity Management Serviceの起動
前述の14章では、Systemプロセスが開始されると、システムの基本的なサービスがいくつか起動されます.起動時にActivityManagerServiceとPackageManagerServiceがあります.システムサーバでActivity Management Serviceを次のように起動します.
frameworks/base/services/java/com/android/server/SystemServer.java :
// Activity manager runs the show.
mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();
startServiceとは、Activity Management ServiceのインスタンスオブジェクトmActivity Management Serviceを作成し、Activity Management Serviceのlooperスレッドを起動することです.SystemServerが基本サービスを開始すると、mActivityManagerServiceのsystemReady関数が呼び出され、HomeActivityが起動します.
2.ホームActivityの起動
SystemServerのメインスレッドで現在呼び出されているsystemReady関数.この関数は、次にstartHomeActivity Locked関数を呼び出してHomeActivityを起動します.具体的には、次のようになります.
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java :
boolean startHomeActivityLocked(int userId, String reason) {
//...
// Home Intent,Intent category android.intent.category.home
Intent intent = getHomeIntent();
ActivityInfo aInfo =
resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
intent.setComponent(new ComponentName(
aInfo.applicationInfo.packageName, aInfo.name));
// Don't do this if the home app is currently being
// instrumented.
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
// home, , app null
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid, true);
if (app == null || app.instrumentationClass == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
// HomeActivity
mStackSupervisor.startHomeActivity(intent, aInfo, reason);
}
}
return true;
}
ここはmStackSupervisorに渡しました.startHomeActivity関数を使用してHomeActivityを起動すると、startActivity Locked関数が呼び出されます.ここでは,2章で一般アプリケーションのactivityを起動する手順を繰り返し,これ以上述べることはない.ここで、LauncherのManifestにはandroidのタイプが示されている.intent.category.ホーム、だから起動したのはLaucherアプリです.
3.Launcher展示応用
次に、LauncherのonCreate関数から始めます.コードの一部は次のとおりです.
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java :
LauncherAppState app = LauncherAppState.getInstance();
// launcher mModel callback
mModel = app.setLauncher(this);
if (!mRestoring) {
if (DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE) {
// If the user leaves launcher, then we should just load items asynchronously when
// they return.
mModel.startLoader(PagedView.INVALID_RESTORE_PAGE);
} else {
// We only load the page synchronously if the user rotates (or triggers a
// configuration change) while launcher is in the foreground
//
mModel.startLoader(mWorkspace.getRestorePage());
}
}
ここでmModelは、アプリケーション情報のロードを担当するLauncherModelオブジェクトです.リロードされたstartLoader関数:
public void startLoader(int synchronousBindPage, int loadFlags) {
//...
synchronized (mLock) {
//...
// Don't bother to start the thread if we know it's not going to do anything
if (mCallbacks != null && mCallbacks.get() != null) {
// ,
// If there is already one running, tell it to stop.
stopLoaderLocked();
//
mLoaderTask = new LoaderTask(mApp.getContext(), loadFlags);
if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE
//...
} else {
// workThread
sWorkerThread.setPriority(Thread.NORM_PRIORITY);
//sWorker sWorkerThread Handler
sWorker.post(mLoaderTask);
}
}
}
}
すべてのインストールされたアプリケーション情報をロードするのは比較的時間がかかるプロセスであるため、非同期スレッドに渡して処理する必要があります.ここではまずロードタスクmLoaderTaskを作成し、sWorkerThreadに渡して処理します.sWorkerThreadはHandlerThreadであり、HandlerThreadは独立したスレッドであり、独自のlooperを持っていることを知っています.mLoaderTaskロードタスクは1回で完了しますが、なぜHandlerThreadで他のタスクを待つ必要があるのでしょうか.デスクトップアプリケーションは動的に追加および削除できるため、アプリケーションのロードは頻繁である可能性があります.ここでHandlerThreadを使用すると、ロードスレッドの重複作成を回避できます.
次はLoaderTaskを見てみましょう.run関数で具体的にどのようなタスクをしましたか.
packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.java :
public void run() {
synchronized (mLock) {
if (mStopped) {
return;
}
mIsLoaderTaskRunning = true;
}
// Optimize for end-user experience: if the Launcher is up and // running with the
// All Apps interface in the foreground, load All Apps first. Otherwise, load the
// workspace first (default).
keep_running: {
if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
// workspace
loadAndBindWorkspace();
if (mStopped) {
break keep_running;
}
waitForIdle();
// second step
if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
//
loadAndBindAllApps();
}
//...
}
WorkSpaceはAndroidデスクトップの分割画面で、各分割画面にはいくつかのアプリケーションがあります.ワークスペースをロードしてから、アプリケーションをロードするとユーザーの心理的な予想に合いますか?関数loadAndBindAllAppsは、アプリケーションがロードされたかどうかを判断し、情報がロードされている場合は、appをデスクトップに直接表示すればよい.ない場合は、次のような関数loadAllAppsを呼び出す必要があります.
packages/apps/Launcher3/src/com/android/luancher3/LauncherModel.java :
private void loadAllApps() {
final Callbacks oldCallbacks = mCallbacks.get();
// Clear the list of apps
mBgAllAppsList.clear();
for (UserHandleCompat user : profiles) {
// Query for the set of apps
// app , PackageManagerService
final List apps = mLauncherApps.getActivityList(null, user);
// Create the ApplicationInfos
for (int i = 0; i < apps.size(); i++) {
LauncherActivityInfoCompat app = apps.get(i);
// AppInfo
// This builds the icon bitmaps.
mBgAllAppsList.add(new AppInfo(mContext, app, user, mIconCache));
}
}
//...
// Huh? Shouldn't this be inside the Runnable below?
final ArrayList added = mBgAllAppsList.added;
mBgAllAppsList.added = new ArrayList();
// Launcher HandlerThread
// , ui ,mHandler Handler
// Post callback on main thread
mHandler.post(new Runnable() {
public void run() {
// callback launcher
final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
if (callbacks != null) {
//
callbacks.bindAllApplications(added);
//...
} else {
//...
}
}
});
//...
}
mLauncherApps.getActivity Listがapp情報を取得する方法は、PackageManagerに要求を送信することによって実現される.次にLauncherメインスレッドに戻り、アプリケーションアイコンの表示を開始します.まず、このコールバック関数を見てみましょう.
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java :
/**
* Add the icons for all apps.
*
* Implementation of the method from LauncherModel.Callbacks.
*/
public void bindAllApplications(final ArrayList apps) {
//...
if (mAppsView != null) {
//mAppsView view
mAppsView.setApps(apps);
}
//...
}
mAppsViewはviewのコンテナであり、AlphabeticalAppsListリストを維持し、アプリケーションの情報を保存します.新しいアプリケーション情報を追加すると、ホーム上のアプリケーションが更新されます.ホーム上のアイコンがクリックされると、アプリケーションの起動がトリガーされます.