ITPub博客

首页 > IT职业 > IT职场 > Android App应用启动流程(一)

Android App应用启动流程(一)

IT职场 作者:zybing 时间:2021-09-09 09:16:32 0 删除 编辑

本篇源码分析基于Android8.0  API 26
关于Android源码查看:
你可以去看这里:https://android.googlesource.com/platform/frameworks/base/ 在线查看,也可以在Android Studio里面关联源码,也可以完全下载自己去编译

https://android.googlesource.com/platform/packages/apps/

Launcher中的App列表使用的RecyclerView

//public class AllAppsRecyclerView extends BaseRecyclerView//public abstract class BaseRecyclerView extends RecyclerView//AllAppsRecyclerView最终继承自RecyclerView

这个Activity叫做Launcher.java,既然是RecyclerView,我们很自然的想到了item点击事件,item点击事件其实是对item设置的View.OnClickListener事件,恰巧Launcher实现了这个事件

/**
 * Default launcher application.
 */public class Launcher extends BaseActivity
        implements LauncherExterns, View.OnClickListener, OnLongClickListener,                   LauncherModel.Callbacks, View.OnTouchListener, LauncherProviderChangeListener,                   AccessibilityManager.AccessibilityStateChangeListener,                   WallpaperColorInfo.OnThemeChangeListener {

那么是不是这里就是用来处理RecyclerView应用图标的点击事件呢?答案是yes
给AllAppsRecyclerView设置adapter被封装到了AllAppsContainerView里面,然后AllAppsContainerView里面

mAdapter = new AllAppsGridAdapter(mLauncher, mApps, mLauncher, this);

AllAppsGridAdapter

/**
 * The grid view adapter of all the apps.
 */
public class AllAppsGridAdapter extends RecyclerView.Adapter {    ...
    //AllAppsGridAdapter构造函数传入iconClickListener
    public AllAppsGridAdapter(Launcher launcher, AlphabeticalAppsList apps, View.OnClickListener
            iconClickListener, View.OnLongClickListener iconLongClickListener) {
        Resources res = launcher.getResources();
        mLauncher = launcher;
        mApps = apps;
        mEmptySearchMessage = res.getString(R.string.all_apps_loading_message);
        mGridSizer = new GridSpanSizer();
        mGridLayoutMgr = new AppsGridLayoutManager(launcher);
        mGridLayoutMgr.setSpanSizeLookup(mGridSizer);
        mLayoutInflater = LayoutInflater.from(launcher);
        mIconClickListener = iconClickListener;
        mIconLongClickListener = iconLongClickListener;        if (FeatureFlags.LAUNCHER3_PHYSICS) {
            mSpringAnimationHandler = new SpringAnimationHandler(
                    SpringAnimationHandler.Y_DIRECTION, new AllAppsSpringAnimationFactory());
        }
    }    ...
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        switch (viewType) {
            case VIEW_TYPE_ICON:
            case VIEW_TYPE_PREDICTION_ICON:
                //icon点击事件
                BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate(
                        R.layout.all_apps_icon, parent, false);
                icon.setOnClickListener(mIconClickListener);
                icon.setOnLongClickListener(mIconLongClickListener);
                icon.setLongPressTimeout(ViewConfiguration.getLongPressTimeout());
                icon.setOnFocusChangeListener(mIconFocusListener);
                // Ensure the all apps icon height matches the workspace icons in portrait mode.
                icon.getLayoutParams().height = mLauncher.getDeviceProfile().allAppsCellHeightPx;                return new ViewHolder(icon);            ...
        }
    }    ...}

可见这个点击事件被设置上了,现在我们回去看看Launcher.java这个Activity里面的onClick事件

/**
 * Launches the intent referred by the clicked shortcut.
 *
 * @param v The view representing the clicked shortcut.
 */public void onClick(View v) {
    ...

    Object tag = v.getTag();    if (tag instanceof ShortcutInfo) {
        onClickAppShortcut(v);
    } else if (tag instanceof FolderInfo) {        if (v instanceof FolderIcon) {
            onClickFolderIcon(v);
        }
    } else if ((v instanceof PageIndicator) ||
        (v == mAllAppsButton && mAllAppsButton != null)) {
        onClickAllAppsButton(v);
    } else if (tag instanceof AppInfo) {        //执行这里
        startAppShortcutOrInfoActivity(v);
    } else if (tag instanceof LauncherAppWidgetInfo) {        if (v instanceof PendingAppWidgetHostView) {
            onClickPendingWidget((PendingAppWidgetHostView) v);
        }
    }
}//拿到应用信息,执行startActivitySafely(v, intent, item)private void startAppShortcutOrInfoActivity(View v) {
    ItemInfo item = (ItemInfo) v.getTag();
    Intent intent;    if (item instanceof PromiseAppInfo) {
        PromiseAppInfo promiseAppInfo = (PromiseAppInfo) item;
        intent = promiseAppInfo.getMarketIntent();
    } else {
        intent = item.getIntent();
    }    if (intent == null) {        throw new IllegalArgumentException("Input must have a valid intent");
    }    boolean success = startActivitySafely(v, intent, item);
    getUserEventDispatcher().logAppLaunch(v, intent); // TODO for discovered apps b/35802115
    if (success && v instanceof BubbleTextView) {
        mWaitingForResume = (BubbleTextView) v;
        mWaitingForResume.setStayPressed(true);
    }
}public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
    ...    // Only launch using the new animation if the shortcut has not opted out (this is a
    // private contract between launcher and may be ignored in the future).
    boolean useLaunchAnimation = (v != null) &&
            !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
    Bundle optsBundle = useLaunchAnimation ? getActivityLaunchOptions(v) : null;
    UserHandle user = item == null ? null : item.user;    // Prepare intent
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);    if (v != null) {
        intent.setSourceBounds(getViewBounds(v));
    }    try {        if (Utilities.ATLEAST_MARSHMALLOW
                && (item instanceof ShortcutInfo)
                && (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
                 || item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
                && !((ShortcutInfo) item).isPromise()) {            // Shortcuts need some special checks due to legacy reasons.
            startShortcutIntentSafely(intent, optsBundle, item);
        } else if (user == null || user.equals(Process.myUserHandle())) {            // Could be launching some bookkeeping activity
            startActivity(intent, optsBundle);
        } else {
            LauncherAppsCompat.getInstance(this).startActivityForProfile(
                    intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
        }        return true;
    } catch (ActivityNotFoundException|SecurityException e) {
        Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
        Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
    }    return false;
}

可以看到最后执行的是startActivity方法,startActivity是Activity的方法,关于app图标点击事件先讲到这。

原文出处

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/855/viewspace-2801645/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2008-06-02

  • 博文量
    103
  • 访问量
    348205