一、Intent Flags:控制Activity启动模式与行为
Intent
的 Flags 是一种强大的“附加信息”,用于指示系统如何启动 Activity
或如何处理任务栈。
1. 常用 Flags 解析
Flag | 作用 |
---|---|
Intent.FLAG_ACTIVITY_NEW_TASK |
在新的任务栈中启动 Activity 。常用于从 Service 或 BroadcastReceiver 启动 Activity 。 |
Intent.FLAG_ACTIVITY_CLEAR_TOP |
如果目标 Activity 已在栈中,清除其上的所有 Activity ,将其带到栈顶。 |
Intent.FLAG_ACTIVITY_SINGLE_TOP |
如果目标 Activity 已在栈顶,则复用它,不创建新实例。 |
Intent.FLAG_ACTIVITY_CLEAR_TASK |
清除启动 Activity 的任务栈中的所有 Activity ,然后在该栈中启动新 Activity 。通常与 NEW_TASK 一起使用。 |
Intent.FLAG_ACTIVITY_NO_HISTORY |
启动的 Activity 不会留在任务栈中,用户无法通过返回键回到它。 |
Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
启动的 Activity 不会出现在最近任务列表中。 |
2. 实战示例:实现“单例”Activity
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
// 这通常用于“退出登录”或“重新登录”后,清空整个任务栈,只保留主界面
startActivity(intent);
3. 动态修改启动模式
// 从通知栏启动 Activity,确保它在自己的任务栈
Intent intent = new Intent(this, NotificationActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
✅ 最佳实践:理解 Flags 的组合效果,避免滥用导致任务栈混乱。
二、Bundle 的高级用法:不仅仅是数据容器
Bundle
除了传递数据,还可以携带一些特殊的“附加信息”。
1. 传递 Parcelable/Serializable 的复杂对象
我们已经知道 Parcelable
是高效传递对象的方式。但 Bundle
本身也实现了 Parcelable
,这意味着你可以将一个 Bundle
作为值放入另一个 Bundle
。
Bundle userBundle = new Bundle();
userBundle.putString("name", "张三");
userBundle.putInt("age", 25);
Bundle mainBundle = new Bundle();
mainBundle.putBundle("user_info", userBundle); // Bundle 嵌套
mainBundle.putString("source", "login");
intent.putExtras(mainBundle);
2. 传递 SparseArray
对于 int
作为 key 的映射,使用 SparseArray
比 HashMap
更省内存。
SparseArray<String> sparseArray = new SparseArray<>();
sparseArray.put(1, "选项一");
sparseArray.put(2, "选项二");
intent.putExtra("options", sparseArray);
⚠️ 注意:
SparseArray
必须是Parcelable
类型(如SparseArray<String>
)。
三、AndroidManifest.xml 中的 <meta-data>:静态附加信息
<meta-data>
标签允许你在 AndroidManifest.xml
中为 Activity
(或 Application
、Service
等)添加静态的、键值对形式的附加信息。
1. 在 Manifest 中定义
<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>
<!-- 添加附加信息 -->
<meta-data
android:name="com.example.APP_THEME"
android:value="dark" />
<meta-data
android:name="com.example.MAX_RETRY"
android:value="3" />
<meta-data
android:name="com.example.CONFIG"
android:resource="@xml/app_config" /> <!-- 引用资源文件 -->
</activity>
2. 在代码中读取
try {
ActivityInfo ai = getPackageManager().getActivityInfo(
getComponentName(), PackageManager.GET_META_DATA);
Bundle metaData = ai.metaData;
if (metaData != null) {
String theme = metaData.getString("com.example.APP_THEME");
int maxRetry = metaData.getInt("com.example.MAX_RETRY");
int configResId = metaData.getInt("com.example.CONFIG");
Log.d("MetaData", "Theme: " + theme + ", Max Retry: " + maxRetry);
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
✅ 典型应用场景:
- 配置第三方 SDK(如地图、推送)。
- 定义 Activity 的主题、行为模式。
- 存储编译时常量。
四、深度链接(Deep Linking)与 App Links:URL 附加信息
通过 URL 直接打开应用内的特定 Activity
,URL 本身携带的参数就是一种强大的“附加信息”。
1. 配置 Intent Filter
<activity android:name=".ProductDetailActivity">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- 响应 http 和 https -->
<data android:scheme="https" android:host="www.example.com" android:pathPrefix="/product" />
</intent-filter>
</activity>
2. 在 Activity 中解析 URL 信息
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_product_detail);
Intent intent = getIntent();
String action = intent.getAction();
Uri data = intent.getData();
if (Intent.ACTION_VIEW.equals(action) && data != null) {
// 解析 URL
String productId = data.getLastPathSegment(); // /product/123 -> "123"
String queryParam = data.getQueryParameter("utm_source"); // 获取查询参数
Log.d("DeepLink", "Product ID: " + productId + ", Source: " + queryParam);
// 加载商品详情
loadProduct(productId);
}
}
✅ 优势:
- 实现应用内外无缝跳转。
- 用于营销推广(UTM 参数追踪)。
- 提升用户体验。
五、利用附加信息实现高级功能
1. 动态配置 Activity 行为
结合 <meta-data>
和 Intent Flags
,可以实现 Activity
的“多态”行为。
<!-- 在 Manifest 中 -->
<meta-data android:name="com.example.FULLSCREEN" android:value="true" />
// 在 Activity.onCreate() 中
Bundle metaData = getPackageManager()
.getActivityInfo(getComponentName(), PackageManager.GET_META_DATA).metaData;
if (metaData != null && metaData.getBoolean("com.example.FULLSCREEN")) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
2. 传递“上下文”信息
intent.putExtra("navigation_source", "notification"); // 告知目标页面是从通知进入的
intent.putExtra("should_refresh", true); // 提示目标页面需要刷新数据
目标 Activity
可根据这些“上下文”信息调整 UI 或行为。
六、最佳实践与注意事项
- 安全第一:来自外部(如 URL、其他应用)的附加信息必须进行严格校验,防止恶意数据。
- 避免滥用:不要通过
Intent
传递大量数据或复杂对象,考虑使用数据库或内存缓存。 - 清理资源:在
onDestroy()
中清理与附加信息相关的资源(如监听器、临时文件)。 - 文档化:为自定义的
meta-data
名称和Intent
键名添加清晰的注释或常量定义。 - 测试覆盖:确保所有可能的附加信息组合都有对应的处理逻辑和测试用例。
七、总结:Activity 附加信息全景图
信息类型 | 用途 | 存储/传递方式 |
---|---|---|
用户数据 | 业务逻辑所需 | Intent.putExtra() , Bundle |
启动指令 | 控制任务栈、启动模式 | Intent Flags |
静态配置 | 编译时确定的元信息 | <meta-data> 标签 |
动态上下文 | 传递导航来源、行为提示 | Intent 自定义键 |
网络入口 | 从外部链接进入应用 | 深度链接 (Deep Link) |
八、结语
感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!