4、车机应用基础:Activity生命周期、Intent与IntentFilter、布局文件基础、AndroidManifest.xml详解

各位同学,欢迎来到第四章。这一章可以说是车机应用开发的「地基」。你想想看,一个车机应用从启动到关闭,系统是怎么管理它的?不同页面之间怎么跳转?界面长什么样又由谁说了算?

嗯,这些问题,我们今天一次性讲清楚。我个人习惯把这一章叫做「车机应用的骨架与血脉」——骨架是布局和清单文件,血脉就是Activity和Intent。

4.1 Activity生命周期:车机应用的「生老病死」

Activity是什么?说白了,它就是车机屏幕上的一扇「窗口」。你看到的导航界面、音乐播放界面,背后都是一个Activity在撑着。

但系统资源是有限的,尤其是车机,内存比手机还紧张。所以系统会随时「回收」那些看不见的Activity。这就引出了生命周期——系统管理Activity的一套规则。

4.1.1 七个核心回调方法

我直接给你列出来,这是面试必考,也是开发必用的:

回调方法 触发时机 典型用途
onCreate() Activity第一次创建 初始化布局、绑定数据、恢复状态
onStart() Activity即将可见 开始动画、注册广播
onResume() Activity获得焦点,可交互 启动传感器、恢复音乐播放
onPause() Activity失去焦点,但部分可见 保存草稿、暂停动画
onStop() Activity完全不可见 释放资源、停止定位
onDestroy() Activity被销毁 清理内存、解绑服务
onRestart() Activity从停止状态重新启动 重新加载数据

车机场景特别提醒:车机不像手机,用户可能随时切换应用(比如导航切到音乐),也可能因为倒车影像突然抢占屏幕。所以onPause和onStop里的逻辑一定要轻量,别做耗时操作。

4.1.2 生命周期流转的三种典型路径

我画个简单的流程给你看:

  • 完整启动:onCreate → onStart → onResume。这是最正常的路径。
  • 按Home键/被覆盖:onPause → onStop。再回来时走onRestart → onStart → onResume。
  • 按返回键:onPause → onStop → onDestroy。彻底拜拜。

我的经验:我曾经在车机项目里犯过一个低级错误——在onStop里做了网络请求,结果用户切到倒车影像再切回来,界面卡死了。后来才明白,onStop里只适合做「保存状态」这种轻活,重活请交给Service或者协程。

4.2 Intent与IntentFilter:车机应用的「通信员」

Activity之间怎么跳转?数据怎么传递?靠的就是Intent。我把它比作「信使」——它带着你的请求和数据,去找对应的组件。

4.2.1 显式Intent vs 隐式Intent

这两种方式,你都得掌握:

  • 显式Intent:直接指定目标组件的包名和类名。比如从MainActivity跳到MusicActivity。简单粗暴,自己人用。
  • 隐式Intent:不指定具体组件,而是声明一个「动作」。比如你想打开一个网页,系统会找到能处理这个动作的浏览器。车机里常用在「分享」或「导航」场景。

代码示例:

// 显式Intent:跳转到音乐播放界面
Intent intent = new Intent(this, MusicActivity.class);
intent.putExtra("song_id", "12345");
startActivity(intent);

// 隐式Intent:打开导航
Intent mapIntent = new Intent(Intent.ACTION_VIEW);
mapIntent.setData(Uri.parse("geo:39.9042,116.4074"));
startActivity(mapIntent);

4.2.2 IntentFilter:告诉系统「我能做什么」

隐式Intent能生效,全靠IntentFilter。它在AndroidManifest.xml里声明,告诉系统:我这个Activity能处理哪些动作。

举个例子,你的车机音乐应用想响应「播放音乐」这个系统广播:

<activity android:name=".MusicPlayerActivity">
    <intent-filter>
        <action android:name="com.example.action.PLAY_MUSIC" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

避坑指南:我曾经在车机项目里遇到一个bug——音乐应用死活收不到系统发来的「播放」指令。查了半天,发现是IntentFilter里忘了加android.intent.category.DEFAULT。记住,startActivity()默认会带上这个category,你不声明,系统就匹配不上。

4.3 布局文件基础:车机界面的「施工图纸」

车机屏幕和手机不一样。手机竖屏多,车机横屏多。而且车机屏幕尺寸五花八门——7寸、10寸、12.3寸都有。所以布局文件怎么写,直接影响用户体验。

4.3.1 五大常用布局

布局名称 特点 车机适用场景
LinearLayout 线性排列,水平或垂直 设置菜单、列表项
RelativeLayout 相对定位,灵活 复杂仪表盘布局
FrameLayout 层叠显示,后添加的在上层 弹窗、悬浮按钮
ConstraintLayout 约束布局,性能好,适配强 推荐用于所有车机界面
GridLayout 网格排列 应用抽屉、快捷功能

我的建议:车机开发,优先用ConstraintLayout。为什么?因为它能减少布局嵌套,提升渲染性能。车机硬件普遍比手机弱,嵌套多了容易掉帧。我见过一个项目,一个界面嵌套了7层LinearLayout,结果启动卡了2秒——后来全改成ConstraintLayout,瞬间流畅。

4.3.2 一个简单的车机布局示例

假设我们要做一个音乐播放界面,顶部是歌曲信息,中间是进度条,底部是控制按钮:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 歌曲名称 -->
    <TextView
        android:id="@+id/tv_song_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="蓝莲花"
        android:textSize="24sp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="40dp"/>

    <!-- 进度条 -->
    <SeekBar
        android:id="@+id/seek_bar"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/tv_song_name"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginStart="20dp"
        android:layout_marginEnd="20dp"
        android:layout_marginTop="30dp"/>

    <!-- 播放/暂停按钮 -->
    <ImageButton
        android:id="@+id/btn_play"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:src="@drawable/ic_play"
        app:layout_constraintTop_toBottomOf="@id/seek_bar"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="30dp"/>

</androidx.constraintlayout.widget.ConstraintLayout>

4.4 AndroidManifest.xml详解:车机应用的「身份证」

每个Android应用根目录下都有一个AndroidManifest.xml。它告诉系统:你是谁?你能做什么?你需要什么权限?

我把它比作「身份证+简历」——系统通过它认识你的应用。

4.4.1 核心配置项

  • package:应用的唯一标识,比如com.example.carplayer。不能重复。
  • application:应用级别的配置,包括图标、主题、是否可调试等。
  • activity:声明每一个Activity。注意,不声明就无法启动。
  • intent-filter:前面讲过了,声明Activity能响应的隐式意图。
  • uses-permission:声明应用需要的权限。车机里常用的是定位、网络、读取存储。

一个典型的车机应用清单文件:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.carmusic">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="车机音乐"
        android:theme="@style/Theme.CarMusic">

        <activity android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity android:name=".MusicPlayerActivity"
            android:exported="false" />

    </application>

</manifest>

避坑指南:我曾经在车机项目里遇到一个诡异问题——应用安装后,点击图标没反应。查了半天,发现是MainActivity的intent-filter里漏写了android.intent.category.LAUNCHER。没有这个,系统就不知道哪个Activity是入口。嗯,这种低级错误,犯一次就记住了。

4.5 本章小结

这一章的内容,说白了就是车机应用的「骨架」和「血脉」:

  • Activity生命周期:掌握七个回调,尤其注意车机场景下的onPause和onStop。
  • Intent与IntentFilter:显式用于内部跳转,隐式用于跨应用通信。IntentFilter别忘了加DEFAULT。
  • 布局文件:优先用ConstraintLayout,减少嵌套,提升性能。
  • AndroidManifest.xml:应用的身份证,所有组件和权限都要在这里声明。

下一章,我们会深入车机特有的「多屏交互」和「车载服务」——那才是车机开发真正有意思的地方。到时候见。

课后练习:试着写一个车机音乐播放器的雏形,包含两个Activity:主界面和播放界面。用显式Intent传递歌曲ID,用隐式Intent响应系统「播放音乐」的广播。布局用ConstraintLayout实现。


公众号:蓝海资料掘金营,微信deep3321