Android App 启动流程 笔记

16 阅读9分钟

Android App 启动流程详解

Android 应用启动是一个复杂的过程,涉及多个系统和应用组件。以下是详细的启动流程分析:

一、点击图标到进程创建

1. Launcher 点击启动

// Launcher 源码简化流程
class LauncherActivity extends Activity {
    void onClick(AppIcon icon) {
        // 创建启动Intent
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        intent.setComponent(new ComponentName(packageName, activityName));
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        
        // 通过ActivityManagerService启动
        ActivityManager.getService().startActivity(...);
    }
}

2. 系统服务处理流程

用户点击图标 
    ↓
Launcher进程调用startActivity()
    ↓
通过Binder IPC调用ActivityManagerService
    ↓
AMS检查权限、进程状态等
    ↓
如果应用进程不存在,创建新进程
    ↓
通过Zygote进程fork新进程
    ↓
新进程调用ActivityThread.main()

二、Zygote 进程创建

1. Zygote 机制

// Zygote进程创建应用进程
class ZygoteProcess {
    // fork新进程
    Process.ProcessStartResult startViaZygote(...) {
        // 准备参数
        ArrayList<String> args = computeArgsForZygote(...);
        
        // 调用Zygote进程fork
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(), args);
    }
}

// ZygoteServer处理fork请求
class ZygoteServer {
    Runnable forkAndSpecialize(...) {
        // fork子进程
        pid = Zygote.forkAndSpecialize(...);
        
        if (pid == 0) {
            // 子进程:设置环境并返回
            handleChildProc(parsedArgs, descriptors, childPipeFd);
        } else {
            // 父进程:等待子进程
            handleParentProc(pid, descriptors, serverPipeFd);
        }
    }
}

2. 应用进程创建后的初始化

// 应用进程入口点
public class ActivityThread {
    public static void main(String[] args) {
        // 1. 准备主线程Looper
        Looper.prepareMainLooper();
        
        // 2. 创建ActivityThread实例
        ActivityThread thread = new ActivityThread();
        
        // 3. 绑定到AMS
        thread.attach(false, startSeq);
        
        // 4. 获取主线程Handler
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        
        // 5. 开始消息循环
        Looper.loop();
    }
    
    private void attach(boolean system, long startSeq) {
        // 获取AMS代理
        final IActivityManager mgr = ActivityManager.getService();
        
        try {
            // 绑定应用进程到AMS
            mgr.attachApplication(mAppThread, startSeq);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }
}

三、Application 创建和初始化

1. Application 创建流程

class ActivityThread {
    // 处理绑定应用
    private void handleBindApplication(AppBindData data) {
        // 1. 设置进程名
        Process.setArgV0(data.processName);
        
        // 2. 创建ContextImpl
        ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
        
        // 3. 创建Instrumentation
        mInstrumentation = new Instrumentation();
        
        // 4. 创建Application
        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
        
        // 5. 设置Application的Context
        app.setBaseContext(appContext);
        
        // 6. 调用Application.onCreate()
        mInstrumentation.callApplicationOnCreate(app);
    }
}

// LoadedApk负责创建Application实例
public class LoadedApk {
    public Application makeApplication(boolean forceDefaultAppClass, 
                                      Instrumentation instrumentation) {
        // 如果Application已经存在,直接返回
        if (mApplication != null) {
            return mApplication;
        }
        
        // 获取Application类名
        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || appClass == null) {
            appClass = "android.app.Application";
        }
        
        try {
            // 1. 创建ClassLoader
            ClassLoader cl = getClassLoader();
            
            // 2. 创建Application Context
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            
            // 3. 实例化Application
            Application app = mActivityThread.mInstrumentation
                .newApplication(cl, appClass, appContext);
            
            // 4. 设置到Context
            appContext.setOuterContext(app);
            
            // 5. 添加到ActivityThread
            mActivityThread.mAllApplications.add(app);
            mApplication = app;
            
            return app;
        } catch (Exception e) {
            throw new RuntimeException(...);
        }
    }
}

2. Application.onCreate() 调用时机

// Instrumentation 调用 Application.onCreate()
public class Instrumentation {
    public void callApplicationOnCreate(Application app) {
        // 这就是我们重写的onCreate()被调用的地方
        app.onCreate();
    }
}

四、Activity 启动流程

1. AMS 调度 Activity 启动

// ActivityManagerService 调度Activity启动
class ActivityManagerService {
    // 启动Activity的最终入口
    public final int startActivity(...) {
        return startActivityAsUser(...);
    }
    
    private int startActivityAsUser(...) {
        // 1. 权限检查
        enforceNotIsolatedCaller("startActivity");
        
        // 2. 调用ActivityStarter
        return mActivityStartController.obtainStarter(...)
            .setCaller(caller)
            .setIntent(intent)
            .setResolvedType(resolvedType)
            .execute();
    }
}

// ActivityStarter 实际执行启动
class ActivityStarter {
    int execute() {
        try {
            // 解析Intent
            ResolveInfo rInfo = mSupervisor.resolveIntent(...);
            
            // 收集信息
            ActivityInfo aInfo = mSupervisor.resolveActivity(...);
            
            // 启动Activity
            return startActivityUnchecked(...);
        } finally {
            // 清理
            onExecutionComplete();
        }
    }
}

2. 应用进程接收启动请求

class ActivityThread {
    // 处理启动Activity的请求
    private class H extends Handler {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case LAUNCH_ACTIVITY:
                    handleLaunchActivity((ActivityClientRecord) msg.obj, "LAUNCH_ACTIVITY");
                    break;
                case RESUME_ACTIVITY:
                    handleResumeActivity(...);
                    break;
            }
        }
    }
    
    private void handleLaunchActivity(ActivityClientRecord r, String reason) {
        // 1. 创建Activity
        Activity a = performLaunchActivity(r, null);
        
        if (a != null) {
            // 2. 调用onStart(), onResume()
            handleResumeActivity(r.token, false, r.isForward, reason);
        }
    }
}

3. Activity 实例创建和生命周期

class ActivityThread {
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // 1. 获取ActivityInfo
        ActivityInfo aInfo = r.activityInfo;
        
        // 2. 创建Context
        ContextImpl appContext = createBaseContextForActivity(r);
        
        // 3. 创建Activity实例
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        } catch (Exception e) {
            // 处理异常
        }
        
        // 4. 创建Application(如果还没创建)
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        
        // 5. 调用Activity.attach()
        activity.attach(appContext, this, getInstrumentation(), r.token,
            r.ident, app, r.intent, r.activityInfo, ...);
        
        // 6. 设置主题
        int theme = r.activityInfo.getThemeResource();
        if (theme != 0) {
            activity.setTheme(theme);
        }
        
        // 7. 调用Activity.onCreate()
        if (r.isPersistable()) {
            mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
        } else {
            mInstrumentation.callActivityOnCreate(activity, r.state);
        }
        
        return activity;
    }
}

// Instrumentation 调用生命周期方法
public class Instrumentation {
    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        // 预创建
        prePerformCreate(activity);
        
        // 调用Activity.onCreate()
        activity.performCreate(icicle);
        
        // 后创建
        postPerformCreate(activity);
    }
    
    public void callActivityOnStart(Activity activity) {
        activity.performStart();
    }
    
    public void callActivityOnResume(Activity activity) {
        activity.performResume();
    }
}

五、界面渲染流程

1. Window 和 View 创建

// Activity.attach() 中创建Window
final void attach(Context context, ...) {
    // 1. 创建Window
    mWindow = new PhoneWindow(this, window, activityConfigCallback);
    
    // 2. 设置WindowManager
    mWindow.setWindowManager(
        (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
        mToken, mComponent.flattenToString(),
        (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
    
    // 3. 获取WindowManager
    mWindowManager = mWindow.getWindowManager();
}

// Activity.onCreate() 中设置ContentView
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    // 1. 创建DecorView
    mWindow.getDecorView();
    
    // 2. 设置内容视图
    setContentView(R.layout.activity_main);
    
    // 3. 初始化View
    initViews();
}

// setContentView() 实现
public void setContentView(@LayoutRes int layoutResID) {
    // 1. 获取Window
    getWindow().setContentView(layoutResID);
    
    // 2. 初始化ActionBar
    initWindowDecorActionBar();
}

// PhoneWindow.setContentView()
public void setContentView(int layoutResID) {
    // 1. 如果DecorView不存在,创建它
    if (mContentParent == null) {
        installDecor();
    }
    
    // 2. 加载布局
    mLayoutInflater.inflate(layoutResID, mContentParent);
}

2. ViewRootImpl 和界面渲染

// ActivityThread.handleResumeActivity()
private void handleResumeActivity(IBinder token, ...) {
    // 1. 调用Activity.onResume()
    final Activity a = r.activity;
    a.performResume();
    
    // 2. 获取DecorView
    View decor = r.window.getDecorView();
    
    // 3. 设置DecorView为不可见
    decor.setVisibility(View.INVISIBLE);
    
    // 4. 获取ViewManager(WindowManager)
    ViewManager wm = a.getWindowManager();
    
    // 5. 添加DecorView到Window
    wm.addView(decor, l);
    
    // 6. 设置DecorView为可见
    decor.setVisibility(View.VISIBLE);
    
    // 7. 焦点处理
    a.makeVisible();
}

// WindowManagerImpl.addView()
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    // 创建ViewRootImpl
    ViewRootImpl root = new ViewRootImpl(view.getContext(), display);
    
    // 设置View
    view.setLayoutParams(wparams);
    
    // 添加到列表
    mViews.add(view);
    mRoots.add(root);
    mParams.add(wparams);
    
    // 设置ViewRootImpl
    root.setView(view, wparams, panelParentView);
}

3. 界面绘制流程

// ViewRootImpl.setView()
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    synchronized (this) {
        if (mView == null) {
            mView = view;
            
            // 1. 请求布局
            requestLayout();
            
            // 2. 创建InputChannel
            mInputChannel = new InputChannel();
            
            // 3. 添加到WindowManagerService
            res = mWindowSession.addToDisplay(...);
            
            // 4. 设置Input事件接收
            if (mInputChannel != null) {
                mInputEventReceiver = new WindowInputEventReceiver(...);
            }
        }
    }
}

// ViewRootImpl.requestLayout()
@Override
public void requestLayout() {
    if (!mHandlingLayoutInLayoutRequest) {
        // 检查线程
        checkThread();
        
        // 标记需要布局
        mLayoutRequested = true;
        
        // 安排遍历
        scheduleTraversals();
    }
}

// ViewRootImpl.scheduleTraversals()
void scheduleTraversals() {
    if (!mTraversalScheduled) {
        mTraversalScheduled = true;
        
        // 1. 添加同步屏障
        mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
        
        // 2. 安排Choreographer回调
        mChoreographer.postCallback(
            Choreographer.CALLBACK_TRAVERSAL,
            mTraversalRunnable,
            null);
        
        // 3. 如果需要,发送唤醒消息
        notifyRendererOfFramePending();
    }
}

// 遍历执行的Runnable
final class TraversalRunnable implements Runnable {
    @Override
    public void run() {
        doTraversal();
    }
}

// 执行遍历
void doTraversal() {
    if (mTraversalScheduled) {
        mTraversalScheduled = false;
        
        // 移除同步屏障
        mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
        
        // 执行遍历
        performTraversals();
    }
}

4. performTraversals() - 核心绘制流程

private void performTraversals() {
    // 临时变量
    final View host = mView;
    
    // 1. 测量阶段
    if (mFirst || windowShouldResize || ...) {
        // 执行测量
        performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
    }
    
    // 2. 布局阶段
    if (didLayout) {
        // 执行布局
        performLayout(lp, mWidth, mHeight);
    }
    
    // 3. 绘制阶段
    if (!cancelDraw && !newSurface) {
        if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
            // 处理转场动画
            for (int i = 0; i < mPendingTransitions.size(); ++i) {
                mPendingTransitions.get(i).startChangingAnimations();
            }
            mPendingTransitions.clear();
        }
        
        // 执行绘制
        performDraw();
    }
}

// 三个核心阶段
private void performMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // 调用View.measure()
    mView.measure(widthMeasureSpec, heightMeasureSpec);
}

private void performLayout(WindowManager.LayoutParams lp, 
                          int desiredWindowWidth, int desiredWindowHeight) {
    // 调用View.layout()
    mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
}

private void performDraw() {
    if (!dirty.isEmpty() || mIsAnimating) {
        // 硬件加速绘制
        if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
            // 硬件渲染
            mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);
        } else {
            // 软件绘制
            if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, 
                            scalingRequired, dirty)) {
                return;
            }
        }
    }
}

六、冷启动、温启动、热启动

1. 启动类型对比

类型进程状态启动速度消耗资源执行流程
冷启动进程不存在创建进程 → 创建Application → 创建Activity
温启动进程存在,Activity被销毁中等中等创建Activity(Application已存在)
热启动Activity在后台恢复Activity(onRestart → onStart → onResume)

2. 冷启动详细时间线

// 冷启动时间分布
T0: 点击图标
    ↓
T1: 进程创建完成(fork + 初始化)
    │   ├── Zygote fork: ~50ms
    │   ├── 加载ART: ~100ms
    │   └── 初始化Runtime: ~50ms
    ↓
T2: Application.onCreate()完成
    │   ├── 创建Application: ~20ms
    │   ├── ContentProvider初始化: ~50ms
    │   └── 第三方库初始化: ~100ms
    ↓
T3: Activity.onCreate()完成
    │   ├── 加载主题: ~30ms
    │   ├── 布局inflate: ~80ms
    │   └── View初始化: ~50ms
    ↓
T4: 第一帧绘制完成
    │   ├── 测量/布局: ~30ms
    │   ├── 绘制: ~50ms
    │   └── 同步到屏幕: ~16ms
    ↓
T5: 用户可交互

七、启动优化策略

1. Application 优化

class MyApplication : Application() {
    
    override fun onCreate() {
        super.onCreate()
        
        // ✅ 1. 延迟初始化
        initDelayedComponents()
        
        // ✅ 2. 后台线程初始化
        initInBackground()
        
        // ✅ 3. 按需初始化
        initOnDemand()
        
        // ❌ 避免在主线程做这些:
        // - 文件IO操作
        // - 网络请求
        // - 大量数据库查询
        // - 复杂的计算
    }
    
    private fun initDelayedComponents() {
        // 使用Lifecycle观察者延迟初始化
        ProcessLifecycleOwner.get().lifecycle.addObserver(object : LifecycleObserver {
            @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
            fun onCreate() {
                // 延迟初始化
            }
        })
    }
    
    private fun initInBackground() {
        // 使用WorkManager或Coroutine在后台初始化
        CoroutineScope(Dispatchers.IO).launch {
            // 初始化第三方库等
        }
    }
    
    private fun initOnDemand() {
        // 懒加载模式
        val heavyLibrary by lazy {
            // 第一次使用时才初始化
            HeavyLibrary()
        }
    }
}

2. Activity 优化

class MainActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        // ✅ 1. 在super.onCreate前设置主题
        setTheme(R.style.AppTheme_Launcher)
        
        super.onCreate(savedInstanceState)
        
        // ✅ 2. 异步加载数据
        loadDataAsync()
        
        // ✅ 3. 延迟加载View
        setContentView(R.layout.activity_main)
        
        // ✅ 4. 分批初始化View
        initEssentialViews()
        postDelayed({ initSecondaryViews() }, 300)
        
        // ✅ 5. 使用ViewStub延迟加载复杂布局
        findViewById<ViewStub>(R.id.stub_complex_layout).apply {
            setOnInflateListener { stub, inflated ->
                // 布局被inflate时初始化
                initComplexViews(inflated)
            }
        }
    }
    
    private fun loadDataAsync() {
        viewModelScope.launch(Dispatchers.IO) {
            val data = repository.loadData()
            withContext(Dispatchers.Main) {
                // 更新UI
            }
        }
    }
    
    private fun initEssentialViews() {
        // 只初始化必要的View
        toolbar = findViewById(R.id.toolbar)
        recyclerView = findViewById(R.id.recycler_view)
    }
    
    private fun initSecondaryViews() {
        // 延迟初始化次要View
        fab = findViewById(R.id.fab)
        bottomNavigation = findViewById(R.id.bottom_nav)
    }
}

3. 布局优化

<!-- 使用ConstraintLayout减少层级 -->
<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <!-- 避免嵌套LinearLayout -->
    
    <!-- 使用merge标签减少层级 -->
    <merge>
        <!-- 子布局内容 -->
    </merge>
    
    <!-- 使用ViewStub延迟加载 -->
    <ViewStub
        android:id="@+id/stub_heavy_view"
        android:layout="@layout/heavy_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
        
</androidx.constraintlayout.widget.ConstraintLayout>

4. 启动器模式

// 启动任务管理器
object AppStartupManager {
    
    private val tasks = mutableListOf<StartupTask>()
    private val executor = Executors.newFixedThreadPool(4)
    
    fun addTask(task: StartupTask) {
        tasks.add(task)
    }
    
    fun start(onComplete: () -> Unit) {
        // 1. 立即执行的任务(在主线程)
        val immediateTasks = tasks.filter { it.priority == Priority.IMMEDIATE }
        immediateTasks.forEach { it.execute() }
        
        // 2. 后台执行的任务
        val backgroundTasks = tasks.filter { it.priority == Priority.BACKGROUND }
        backgroundTasks.forEach { task ->
            executor.submit {
                task.execute()
            }
        }
        
        // 3. 延迟执行的任务
        val delayedTasks = tasks.filter { it.priority == Priority.DELAYED }
        Handler(Looper.getMainLooper()).postDelayed({
            delayedTasks.forEach { it.execute() }
            onComplete()
        }, 1000)
    }
}

// 启动任务定义
interface StartupTask {
    val priority: Priority
    fun execute()
}

enum class Priority {
    IMMEDIATE,    // 立即执行(主线程)
    BACKGROUND,   // 后台执行
    DELAYED       // 延迟执行
}

// 使用示例
class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        
        AppStartupManager.apply {
            addTask(object : StartupTask {
                override val priority = Priority.IMMEDIATE
                override fun execute() {
                    // 初始化Analytics
                }
            })
            
            addTask(object : StartupTask {
                override val priority = Priority.BACKGROUND
                override fun execute() {
                    // 初始化数据库
                }
            })
            
            addTask(object : StartupTask {
                override val priority = Priority.DELAYED
                override fun execute() {
                    // 预加载数据
                }
            })
        }
        
        // 启动所有任务
        AppStartupManager.start {
            // 所有任务完成后的回调
        }
    }
}

5. 使用 Jetpack Startup 库

// 添加依赖
dependencies {
    implementation "androidx.startup:startup-runtime:1.1.1"
}

// 定义初始化器
class AnalyticsInitializer : Initializer<Analytics> {
    override fun create(context: Context): Analytics {
        // 初始化Analytics SDK
        return Analytics.init(context)
    }
    
    override fun dependencies(): List<Class<out Initializer<*>>> {
        // 依赖其他初始化器
        return listOf(DatabaseInitializer::class.java)
    }
}

// 自动初始化配置
<provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    android:exported="false"
    tools:node="merge">
    
    <meta-data
        android:name="com.example.AnalyticsInitializer"
        android:value="androidx.startup" />
        
</provider>

// 手动初始化(按需)
AppInitializer.getInstance(context)
    .initializeComponent(AnalyticsInitializer::class.java)

八、启动时间测量

1. 使用 ADB 测量

# 测量冷启动时间
adb shell am start-activity -W -n com.example/.MainActivity

# 输出示例:
# Starting: Intent { cmp=com.example/.MainActivity }
# Status: ok
# Activity: com.example/.MainActivity
# ThisTime: 1000  # 当前Activity启动耗时
# TotalTime: 1000 # 应用启动总耗时(包括前一个Activity pause时间)
# WaitTime: 1000  # AMS启动Activity的总耗时
# Complete

# 测量完全启动时间(直到用户可交互)
adb shell am start-activity -S -R 10 -W com.example/.MainActivity

# 使用systrace分析启动性能
python systrace.py -a com.example -o mytrace.html sched gfx view wm am

2. 代码中测量

class MyApplication : Application() {
    
    override fun onCreate() {
        super.onCreate()
        
        // 1. 使用Firebase Performance Monitoring
        FirebasePerformance.getInstance()
            .newTrace("app_start_trace")
            .start()
        
        // 2. 自定义测量
        val startTime = System.currentTimeMillis()
        
        // ... 初始化代码
        
        val endTime = System.currentTimeMillis()
        val duration = endTime - startTime
        
        // 记录到Analytics
        FirebaseAnalytics.getInstance(this).logEvent("app_start_duration", bundleOf(
            "duration_ms" to duration
        ))
    }
}

class MainActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        // 测量Activity创建时间
        val activityStartTime = System.currentTimeMillis()
        
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // 等待第一帧绘制
        window.decorView.post {
            val activityEndTime = System.currentTimeMillis()
            val activityDuration = activityEndTime - activityStartTime
            
            // 记录Activity启动时间
            logDuration("activity_create", activityDuration)
        }
    }
    
    override fun onWindowFocusChanged(hasFocus: Boolean) {
        super.onWindowFocusChanged(hasFocus)
        
        if (hasFocus) {
            // 此时用户可以与界面交互
            val appStartTime = getSharedPreferences("app_start", MODE_PRIVATE)
                .getLong("start_time", 0)
            
            if (appStartTime > 0) {
                val totalDuration = System.currentTimeMillis() - appStartTime
                logDuration("app_start_total", totalDuration)
            }
        }
    }
}

九、启动白屏/黑屏问题

1. 启动主题优化

<!-- styles.xml -->
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    <!-- 正常主题 -->
</style>

<style name="AppTheme.Launcher" parent="AppTheme">
    <!-- 启动主题,避免白屏 -->
    <item name="android:windowBackground">@drawable/launch_screen</item>
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:windowTranslucentStatus">true</item>
</style>

<!-- launch_screen.xml -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/primaryDark"/>
    <item>
        <bitmap
            android:gravity="center"
            android:src="@mipmap/ic_launcher"/>
    </item>
</layer-list>

2. 在 Manifest 中应用

<application
    android:name=".MyApplication"
    android:theme="@style/AppTheme.Launcher">
    
    <activity
        android:name=".MainActivity"
        android:theme="@style/AppTheme">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>
    
</application>

3. 在 Activity 中切换主题

class MainActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        // 在super.onCreate之前设置正常主题
        setTheme(R.style.AppTheme)
        
        super.onCreate(savedInstanceState)
        
        // 监听第一帧绘制完成
        val content = findViewById<View>(android.R.id.content)
        content.viewTreeObserver.addOnPreDrawListener(
            object : ViewTreeObserver.OnPreDrawListener {
                override fun onPreDraw(): Boolean {
                    // 第一帧准备绘制时,移除启动主题
                    content.viewTreeObserver.removeOnPreDrawListener(this)
                    
                    // 可以在这里执行一些动画
                    startContentAnimation()
                    
                    return true
                }
            }
        )
    }
}

总结

Android App 启动流程核心要点:

  1. 进程创建阶段

    • Zygote fork 新进程
    • 调用 ActivityThread.main()
    • 绑定到 AMS
  2. Application 初始化

    • 创建 Application 实例
    • 调用 Application.onCreate()
    • ContentProvider 初始化
  3. Activity 启动

    • 创建 Activity 实例
    • 调用生命周期方法(onCreate → onStart → onResume)
    • Window 和 View 创建
  4. 界面渲染

    • ViewRootImpl 创建
    • 执行 measure、layout、draw
    • 通过 Choreographer 同步到屏幕
  5. 优化策略

    • 延迟初始化
    • 异步加载
    • 布局优化
    • 启动主题优化
    • 使用启动器模式
  6. 性能测量

    • 使用 ADB 命令
    • 代码埋点
    • systrace 分析

理解完整的启动流程有助于:

  • 优化应用启动性能
  • 解决启动白屏/黑屏问题
  • 设计合理的初始化策略
  • 提升用户体验