AMS之Activity启动(AndroidV)

一:背景

    Activity作为Android四大组件之一,用途之广、作用之重要想必不需要多做赘述,下面将从Launcher点击Dialer图标这个流程来剖析Activity是如何启动的。

PS:点击事件在Launcher中的传递本篇文章不涉及,流程起始点是ContextImpl.startActivity

二:Activity启动流程

    2.1 准备工作

    2.1.1 ContextImpl.startActivity

      最终会通过ActivityTaskManagerService调用到ActivityStarter,在ActivityStarter中做真正Activity启动工作。

//frameworks/base/core/java/android/app/ContextImpl.java
    public void startActivity(Intent intent) {
        warnIfCallingFromSystemProcess();
        startActivity(intent, null);
    }

//frameworks/base/core/java/android/app/ContextImpl.java
    public void startActivity(Intent intent, Bundle options) {
        ...
        mMainThread.getInstrumentation().execStartActivity(
                getOuterContext(), mMainThread.getApplicationThread(), null,
                (Activity) null, intent, -1, options);
    }

//frameworks/base/core/java/android/app/Instrumentation.java
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        ...
        try {
            intent.migrateExtraStreamToClipData(who);
            intent.prepareToLeaveProcess(who);
            //启动Activity
            int result = ActivityTaskManager.getService().startActivity(whoThread,
                    who.getOpPackageName(), who.getAttributionTag(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()), token,
                    target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
            notifyStartActivityResult(result, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

//frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
    public final int startActivity(IApplicationThread caller, String callingPackage,
            String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
            Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }

//frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
    private int startActivityAsUser(IApplicationThread caller, String callingPackage,
            @Nullable String callingFeatureId, Intent intent, String resolvedType,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
        ...
        return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setCallingFeatureId(callingFeatureId)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(opts)
                .setUserId(userId)
                .execute();
    }

2.1.2 ActivityStarter.execute

  这里主要完成以下工作

  • 校验Activity启动合法性,判断是否需要拦截Activity启动
  • 创建ActivityRecord对象
  • 校准Activity启动的flag,并根据flag判断是否有可以复用的task,没有则创建新的任务栈
  • 计算Activity的参数,如窗口区域、窗口模式等
  • 开始播放Activity启动时startingWindow动画
//frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
    int execute() {
        try {
            //执行开始即开始启动Activity
            onExecutionStarted();
            ...
            int res = START_CANCELED;
            synchronized (mService.mGlobalLock) {
                ...
                try {
                    ...
                    res = executeRequest(mRequest);
                } finally {
                    ...
                }
                ...
            }
            ...
        } finally {
            //执行结束即Activity启动结束
            onExecutionComplete();
        }
    ...
    }

//frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
    private int executeRequest(Request request) {
        ...
        //判断是否需要拦截Activity启动
        if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, inTaskFragment,
                callingPid, callingUid, checkedOptions, suggestedLaunchDisplayArea)) {
            ...
            intentGrants = null;
        }
        ...
        //创建ActivityRecord对象
        final ActivityRecord r = new ActivityRecord.Builder(mService)
                ...
                .build();
        ...
        //启动Activity
        mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
                request.voiceInteractor, startFlags, checkedOptions,
                inTask, inTaskFragment, balVerdict, intentGrants, realCallingUid);
        ...
    }

//frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, ActivityOptions options, Task inTask,
            TaskFragment inTaskFragment,
            BalVerdict balVerdict,
            NeededUriGrants intentGrants, int realCallingUid) {
        ...
        try {
            mService.deferWindowLayout();
            transitionController.collect(r);
            try {
                //开始"startActivityInner" trace的地方
                Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
                //启动Activity
                result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
                        startFlags, options, inTask, inTaskFragment, balVerdict,
                        intentGrants, realCallingUid);
            } catch (Exception ex) {
                Slog.e(TAG, "Exception on startActivityInner", ex);
            } finally {
                //结束"startActivityInner" trace的地方
                Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
                startedActivityRootTask = handleStartResult(r, options, result, newTransition,
                        remoteTransition);
            }
        } finally {
            mService.continueWindowLayout();
        }
        postStartActivityProcessing(r, result, startedActivityRootTask);

        return result;
    }

//frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
    int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, ActivityOptions options, Task inTask,
            TaskFragment inTaskFragment, BalVerdict balVerdict,
            NeededUriGrants intentGrants, int realCallingUid) {
        //初始化状态
        setInitialState(r, options, inTask, inTaskFragment, startFlags, sourceRecord,
                voiceSession, voiceInteractor, balVerdict.getCode(), realCallingUid);
        //校准mLaunchFlags并更新到mIntent中
        computeLaunchingTaskFlags();
        mIntent.setFlags(mLaunchFlags);
        ...
        //根据includeLaunchedFromBubble判断是否有task可以复用,并返回可以复用的task
        final Task reusedTask = resolveReusableTask(includeLaunchedFromBubble);
        ...
        //判断是否有可以使用的现成的task(例如在应用中通过Activity1启动Activity2,启动方式是standard,那么Activity1所在的task就可以给Activity2使用而不需要重新创建一个task)
        final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();
        final boolean newTask = targetTask == null;
        ...
        //计算启动Activity时的参数,例如窗口区域、窗口模式等
        computeLaunchParams(r, sourceRecord, targetTask);
        //检查启动是否被允许
        int startResult = isAllowedToStart(r, newTask, targetTask);

        ...

        final ActivityRecord targetTaskTop = newTask
                ? null : targetTask.getTopNonFinishingActivity();
        if (targetTaskTop != null) {
            //Activity的启动模式是SINGLE_INSTANCE,移除所有有该Activity的任务栈
            if (LAUNCH_SINGLE_INSTANCE == mLaunchMode && mSourceRecord != null
                    && targetTask == mSourceRecord.getTask()) {
                final ActivityRecord activity = mRootWindowContainer.findActivity(mIntent,
                        mStartActivity.info, false);
                if (activity != null && activity.getTask() != targetTask) {
                    activity.destroyIfPossible("Removes redundant singleInstance");
                }
            }
            ...
        }
        //如果当前任务栈的最上层Activity是将要启动的Activity,判断是否需要再次启动Activity(standard模式会再次启动,singletop模式则不会再次启动)
        final Task topRootTask = mPreferredTaskDisplayArea.getFocusedRootTask();
        if (topRootTask != null) {
            startResult = deliverToCurrentTopIfNeeded(topRootTask, intentGrants);
            if (startResult != START_SUCCESS) {
                return startResult;
            }
        }
        ...
        //可用任务栈不存在,创建新的任务栈
        if (mTargetRootTask == null) {
            mTargetRootTask = getOrCreateRootTask(mStartActivity, mLaunchFlags, targetTask,
                    mOptions);
        }
        ...
        //在event log中记录有新的task创建了
        if (newTask) {
            EventLogTags.writeWmCreateTask(mStartActivity.mUserId, startedTask.mTaskId,
                    startedTask.getRootTaskId(), startedTask.getDisplayId());
        }
        //在event log中记录create Activity
        mStartActivity.logStartActivity(EventLogTags.WM_CREATE_ACTIVITY, startedTask);
        ...
        //开始Activity启动过渡动画
        mTargetRootTask.startActivityLocked(mStartActivity, topRootTask, newTask, isTaskSwitch,
                mOptions, sourceRecord);
        //mDoResume为true
        if (mDoResume) {
            final ActivityRecord topTaskActivity = startedTask.topRunningActivityLocked();
            if (!mTargetRootTask.isTopActivityFocusable()
                    || (topTaskActivity != null && topTaskActivity.isTaskOverlay()
                    && mStartActivity != topTaskActivity)) {
                ...
                mTargetRootTask.ensureActivitiesVisible(null /* starting */);
                mTargetRootTask.mDisplayContent.executeAppTransition();
            } else {
                ...
                mRootWindowContainer.resumeFocusedTasksTopActivities(
                        mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
            }
        }
        ...
        //更新最近任务栈
        mSupervisor.mRecentTasks.add(startedTask);
        ...
    }

//frameworks/base/services/core/java/com/android/server/wm/Task.java
    void startActivityLocked(ActivityRecord r, @Nullable Task topTask, boolean newTask,
            boolean isTaskSwitch, ActivityOptions options, @Nullable ActivityRecord sourceRecord) {
        ...
        final DisplayContent dc = mDisplayContent;
        if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {//不需要过渡动画
            ...
        } else {
            //准备过渡动画
            dc.prepareAppTransition(TRANSIT_OPEN);
            mTaskSupervisor.mNoAnimActivities.remove(r);
        }
        ...
        //后台启动
        if (r.mLaunchTaskBehind) {
            ...
        } else if (SHOW_APP_STARTING_PREVIEW && doShow) {//SHOW_APP_STARTING_PREVIEW为true
            ...
            //开始StartingWindow动画
            mWmService.mStartingSurfaceController.showStartingWindow(r, prev, newTask,
                    isTaskSwitch, sourceRecord);
        }
    }

//frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
    boolean resumeFocusedTasksTopActivities(
            Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,
            boolean deferPause) {
        ...
        if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
                || getTopDisplayFocusedRootTask() == targetRootTask)) {
            result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,
                    deferPause);
        }
        ...
    }

//frameworks/base/services/core/java/com/android/server/wm/Task.java
    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
        ...
        try {
            ...
            if (isLeafTask()) {
                if (isFocusableAndVisible()) {
                    someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);
                }
            }
            ...
        }
        ...
    }

//frameworks/base/services/core/java/com/android/server/wm/Task.java
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
        ...
        final boolean[] resumed = new boolean[1];
        final TaskFragment topFragment = topActivity.getTaskFragment();
        resumed[0] = topFragment.resumeTopActivity(prev, options, deferPause);
        forAllLeafTaskFragments(f -> {
            if (topFragment == f) {
                return;
            }
            if (!f.canBeResumed(null /* starting */)) {
                return;
            }
            resumed[0] |= f.resumeTopActivity(prev, options, deferPause);
        }, true);
        return resumed[0];
    }

//frameworks/base/services/core/java/com/android/server/wm/TaskFragment.java
    final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,
            boolean skipPause) {
        ...
        //暂停前一个Activity
        boolean pausing = !skipPause && taskDisplayArea.pauseBackTasks(next);
        ...
        if (pausing) {
            ...
            if (next.attachedToProcess()) {//Activity所属进程已存在
                ...
            } else if (!next.isProcessRunning()) {//Activity所属进程不存在
                ...
                //启动Activity所属进程
                mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,
                        isTop ? HostingRecord.HOSTING_TYPE_NEXT_TOP_ACTIVITY
                                : HostingRecord.HOSTING_TYPE_NEXT_ACTIVITY);
            }
            ...
        }
        ...
        boolean anim = true;
        final DisplayContent dc = taskDisplayArea.mDisplayContent;
        if (prev != null) {
            if (prev.finishing) {
                ...
                if (mTaskSupervisor.mNoAnimActivities.contains(prev)) {
                    ...
                } else {
                    //过渡动画准备完成
                    dc.prepareAppTransition(TRANSIT_CLOSE);
                }
                prev.setVisibility(false);
            } else {
                ...
            }
        } else {
            ...
        }

        if (anim) {
            //播放过渡动画
            next.applyOptionsAnimation();
        } else {
            ...
        }
        ...
        if (next.attachedToProcess()) {
            ...
            //更新CPU统计信息
            mAtmService.updateCpuStats();
            //更新状态
            next.setState(RESUMED, "resumeTopActivity");
            ...
            try {
                ...
                //标记Activity resume
                next.notifyAppResumed();
            ...
    }

2.2 暂停前一个Activity

2.2.1 TaskFragment.startPausing

  获取需要暂停的ActivityRecord(即当前处于resume状态的Activity对应的ActivityRecord),更新需要暂停Activity的状态为PAUSING,调用TaskFragment的schedulePauseActivity做真正暂停Activity的工作

//frameworks/base/services/core/java/com/android/server/wm/TaskDisplayArea.java
    boolean pauseBackTasks(ActivityRecord resuming) {
        final int[] someActivityPaused = {0};
        forAllLeafTasks(leafTask -> {
            //调用Task的pauseActivityIfNeeded来暂定Activity,暂停原因是"pauseBackTasks"
            if (leafTask.pauseActivityIfNeeded(resuming, "pauseBackTasks")) {
                someActivityPaused[0]++;
            }
        }, true /* traverseTopToBottom */);
        return someActivityPaused[0] > 0;
    }

//frameworks/base/services/core/java/com/android/server/wm/Task.java
    boolean pauseActivityIfNeeded(@Nullable ActivityRecord resuming, @NonNull String reason) {
        ...
        forAllLeafTaskFragments((taskFrag) -> {
            final ActivityRecord resumedActivity = taskFrag.getResumedActivity();
            if (resumedActivity != null && !taskFrag.canBeResumed(resuming)) {
                //调用TaskFragment的startPausing继续暂停流程
                if (taskFrag.startPausing(false /* uiSleeping*/, resuming, reason)) {
                    someActivityPaused[0]++;
                }
            }
        }, true /* traverseTopToBottom */);
        ...
    }

//frameworks/base/services/core/java/com/android/server/wm/TaskFragment.java
    boolean startPausing(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming,
            String reason) {
        ...
        //将要暂停的Activity对应的ActivityRecord赋值给prev
        ActivityRecord prev = mResumedActivity;
        ...
        mPausingActivity = prev;
        ...
        //更新状态为PAUSING
        prev.setState(PAUSING, "startPausingLocked");
        prev.getTask().touchActiveTime();
        ...
        if (prev.attachedToProcess()) {
            if (shouldAutoPip && ActivityTaskManagerService.isPip2ExperimentEnabled()) {//画中画模式,不暂停Activity
                ...
            } else if (shouldAutoPip) {//画中画模式,不暂停Activity
                ...
            } else {
                //真正暂停Activity的地方
                schedulePauseActivity(prev, userLeaving, pauseImmediately,
                        false /* autoEnteringPip */, reason);
            }
        }
        ...
        if (mPausingActivity != null) {
            ...
            if (pauseImmediately) {
                //暂停完成
                completePause(false, resuming);
                return false;

            } else {
                ...
            }

        }
        ...
    }

2.2.2 ActivityThread.performPauseActivity

  Activity的暂停是通过PauseActivityItem(Activity 的暂停transaction)来实现。PauseActivityItem会调用ActivityThread,更新Activity的状态为ON_PAUSE,最终通过Activity的performPause来调用到Launcher Activity的onPause函数

//frameworks/base/services/core/java/com/android/server/wm/TaskFragment.java
    void schedulePauseActivity(ActivityRecord prev, boolean userLeaving,
            boolean pauseImmediately, boolean autoEnteringPip, String reason) {
        try {
            ...
            //暂停Activity
<think>我们聚焦于从源码角度分析Activity启动流程,主要环节如下: ### 1. **Launcher发起启动请求** - **入口**:`Launcher`点击应用图标触发`startActivity()` - **关键调用链**: ```java // frameworks/base/core/java/android/app/Activity.java public void startActivity(Intent intent) { mInstrumentation.execStartActivity(...); // 通过Instrumentation发起 } ``` - **跨进程通信**:通过Binder调用到`ActivityTaskManagerService` (ATMS)[^1] ### 2. **ATMS处理启动请求** - **核心逻辑**:`frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java` ```java class ActivityTaskManagerService { int startActivity(...) { return getActivityStartController().obtainStarter(...).execute(); } } ``` - **关键步骤**: - 验证权限及Intent - 创建`ActivityRecord`对象记录Activity信息 - 决策是否新建进程[^1][^2] ### 3. **进程创建(若需新建)** - **调用路径**: ``` ATMS.startProcessAsync() → LocalService.startProcess() → ProcessList.startProcessLocked() ``` - **Zygote孵化**: ```java // frameworks/base/services/core/java/com/android/server/am/ProcessList.java final Process.ProcessStartResult startResult = Process.start(...); ``` - 通过Socket连接Zygote fork新进程[^1] ### 4. **目标进程初始化** - **入口**:`ActivityThread.main()` ```java // frameworks/base/core/java/android/app/ActivityThread.java public static void main(String[] args) { Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); // 绑定到AMS Looper.loop(); } ``` - **绑定系统服务**:通过`ApplicationThread` Binder对象与ATMS通信[^3] ### 5. **Activity实例化与生命周期** - **ATMS回调**:`ApplicationThread.scheduleLaunchActivity()` - **核心处理**: ```java // ActivityThread.handleLaunchActivity() final Activity a = performLaunchActivity(r, customIntent); if (a != null) { handleResumeActivity(...); // 触发onResume() } ``` - **关键源码**: ```java // ActivityThread.performLaunchActivity() Activity activity = mInstrumentation.newActivity(...); // 反射创建实例 Application app = r.packageInfo.makeApplication(...); // 创建Application activity.attach(...); // 关联Context mInstrumentation.callActivityOnCreate(activity, ...); // 回调onCreate() ``` - **视图渲染**:`onCreate()`中调用`setContentView()`触发DecorView创建[^3] ### 6. **界面绘制与显示** - **首帧同步**:`handleResumeActivity()`中触发View绘制 ```java // ActivityThread.handleResumeActivity() wm.addView(decor, layoutParams); // 添加DecorView到WindowManager ``` - **VSync同步流程**: 1. `ViewRootImpl.scheduleTraversals()`请求VSync信号 2. Choreographer通过SF进程同步VSync 3. 收到VSync后执行`performTraversals()`(测量/布局/绘制)[^3] ### 性能优化关键点 1. **进程复用**:通过`android:process`共享进程减少fork开销 2. **异步加载**:在`onCreate()`中延迟加载非必要资源 3. **渲染优化**:使用`<merge>`标签减少视图层级 4. **冷启动加速**:借助StartingWindow展示预览界面 --- §§相关问题§§ 1. `Instrumentation`在Activity启动中承担什么角色? 2. Zygote孵化新进程时如何复制内存页? 3. `ViewRootImpl.performTraversals()`的测量-布局-绘制三个阶段如何协同工作? </think>以下是从源码角度分析的Android Activity启动主要流程环节,涵盖从Launcher点击到界面渲染的核心过程: --- ### 1. **Launcher发起启动请求** - **入口**:`Launcher.onClick()` (packages/apps/Launcher3) - **关键调用链**: ```java // Launcher.java onClick(View v) { startActivitySafely(v, intent, item); // 启动目标应用 } → startActivity(intent) → Instrumentation.execStartActivity() // 跨进程通信枢纽 ``` - **跨进程通信**:通过Binder调用`ActivityTaskManagerService` (ATMS)[^1] --- ### 2. **ATMS处理启动请求** - **核心逻辑**:`ActivityTaskManagerService.startActivity()` ```java // frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java public int startActivity(...) { return getActivityStartController().obtainStarter(intent).execute(); } ``` - **关键步骤**: 1. 解析Intent获取目标Activity信息 2. 检查权限及进程状态 3. 决策是否需创建新进程(`ProcessRecord`) 4. 创建`ActivityRecord`对象[^1] --- ### 3. **进程创建(若需新建)** - **Zygote孵化流程**: ```java // frameworks/base/services/core/java/com/android/server/am/ProcessList.java final Process.ProcessStartResult startResult = Process.start(...); ``` - 通过Socket联系Zygote - fork新进程并执行`ActivityThread.main()` - **内存优化**:Copy-on-Write复用Zygote预加载资源[^1] --- ### 4. **目标进程初始化** - **入口**:`ActivityThread.main()` ```java // frameworks/base/core/java/android/app/ActivityThread.java public static void main(String[] args) { Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); // 绑定到AMS Looper.loop(); } ``` - **关键动作**: - 创建`ApplicationThread` Binder对象 - 通过`ATTACH_APPLICATION`消息注册到AMS[^3] --- ### 5. **Activity实例化与生命周期** - **ATMS回调**:`ApplicationThread.scheduleLaunchActivity()` - **核心处理**: ```java // ActivityThread.handleLaunchActivity() private void handleLaunchActivity(...) { final Activity a = performLaunchActivity(r, customIntent); // 创建实例 handleResumeActivity(...); // 触发onResume() } ``` - **创建细节**: ```java // performLaunchActivity() Activity activity = mInstrumentation.newActivity(...); // 反射创建 Application app = r.packageInfo.makeApplication(...); // 创建Application activity.attach(...); // 关联Context mInstrumentation.callActivityOnCreate(activity, ...); // 回调onCreate() ``` - **视图初始化**:`onCreate()`中调用`setContentView()`触发DecorView创建[^3] --- ### 6. **界面绘制与显示** - **添加到窗口**:`ActivityThread.handleResumeActivity()` ```java wm.addView(decor, layoutParams); // 添加DecorView到WindowManager ``` - **VSync同步绘制**: 1. `ViewRootImpl.scheduleTraversals()`请求VSync信号 2. Choreographer通过`FrameDisplayEventReceiver`接收VSync 3. 执行`performTraversals()`(测量/布局/绘制) 4. SurfaceFlinger合成帧缓存[^3] --- ### 性能优化关键点 1. **进程复用**:通过`android:process`共享进程减少fork开销 2. **异步加载**:在`onCreate()`中延迟初始化非必要资源 3. **渲染管线优化**: ```java // 启用硬件加速 <activity android:hardwareAccelerated="true"/> ``` 4. **冷启动优化**:使用SplashScreen API展示即时预览 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值