天天看點

從源碼看Activity啟動過程(一)LaunchActivity

本文以點選桌面快捷方式啟動app來看源碼

Launcher process    ->   Binder    ->     System process    ->    Binder     ->        Target process

LauncherActivity  -> ActivityManagerProxy ->AMS -> ApplicationThreadProxy -> Instrumentation.newActivity

1、先看LaunchActivity源碼

public abstract class LauncherActivity extends ListActivity {
	//如果通過component、schema啟動一個app,那麼這個mIntent中會有資料
	Intent mIntent;
	...
	private class ActivityAdapter extends BaseAdapter implements Filterable {
        ...
		public ActivityAdapter(IconResizer resizer) {
            ...
            mActivitiesList = makeListItems();
        }
		
        public Intent intentForPosition(int position) {
            if (mActivitiesList == null) {
                return null;
            }
			//mIntent一個空的intent,貌似m
            Intent intent = new Intent(mIntent);
            ListItem item = mActivitiesList.get(position);
            intent.setClassName(item.packageName, item.className);
            if (item.extras != null) {
                intent.putExtras(item.extras);
            }
            return intent;
        }
	}
	
	@Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
		//從adapter中取出點選item的資料封裝成intent
        Intent intent = intentForPosition(position);
        startActivity(intent);//這裡啟動activity
    }
    
    /**
     * 傳回點選的item的app資訊
     */
    protected Intent intentForPosition(int position) {
        ActivityAdapter adapter = (ActivityAdapter) mAdapter;
        return adapter.intentForPosition(position);
    }
	//擷取資料源,Launcher顯示的資料
	public List<ListItem> makeListItems() {
		//關于這個mIntent
        List<ResolveInfo> list = onQueryPackageManager(mIntent);
        onSortResultList(list);
        ArrayList<ListItem> result = new ArrayList<ListItem>(list.size());
        int listSize = list.size();
        for (int i = 0; i < listSize; i++) {
            ResolveInfo resolveInfo = list.get(i);
            result.add(new ListItem(mPackageManager, resolveInfo, null));
        }
        return result;
    }
}
           

關于LauncherActivity中mIntent的作用簡述:

調用鍊

PackageManager->ApplicationPackageManager->PackageManagerService

 >> LauncherActivity.onQueryPackageManager(mIntent) -> PackageManager.queryIntentActivities(queryIntent, 0)

-> ApplicationPackageManager.queryIntentActivities(intent, flag)

-> ApplicationPackageManager.queryIntentActivitiesAsUser(intent, flag, userId)

-> PackageManagerService.queryIntentActivities(Intent intent, String resolvedType, int flags, int userId)

-> PackageManagerService.queryIntentActivitiesInternal(Intent intent, String resolvedType, int flags, int userId)

/**真正的調用在這裡
  * 這裡根據intent中傳入資料在不同範圍比對查詢
  * 比如有些通過schema、component啟動其他程序的app時,intent是有資料的
  */
public class PackageManagerService extends IPackageManager.Stub {
	private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent, String resolvedType, int flags, int userId) {
		if (!sUserManager.exists(userId)) return Collections.emptyList();
		flags = updateFlagsForResolve(flags, userId, intent);
		enforceCrossUserPermission(Binder.getCallingUid(), userId, false /* requireFullPermission */, false /* checkShell */, "query intent activities");
		ComponentName comp = intent.getComponent();
		if (comp == null) {//intent傳入的component
			if (intent.getSelector() != null) {
				intent = intent.getSelector();
				comp = intent.getComponent();
			}
		}
		if (comp != null) {//根據intent傳入的component傳回需要查詢的資料
			final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
			final ActivityInfo ai = getActivityInfo(comp, flags, userId);
			if (ai != null) {
				final ResolveInfo ri = new ResolveInfo();
				ri.activityInfo = ai;
				list.add(ri);
			}
			return list;
		}
		//intent中沒有傳入component
		synchronized (mPackages) {
			/* intent未傳入packageName,需要在整個系統範圍内進行比對查詢
			 * intent有傳入packageName則在指定pkg下比對查詢
			 */
			...
		}
		...
	}
}
           

參考資料

繼續閱讀