06-Activity组件通信与Scheme跳转
Activity 组件通信与 Scheme 跳转
1. Activity 与 Activity 通信
最常见方式是:
Intent + Bundle
示例:
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
Bundle bundle = new Bundle();
bundle.putString("data_string", "数据");
bundle.putInt("data_int", 10);
bundle.putChar("data_char", 'a');
intent.putExtras(bundle);
startActivity(intent);
在 SecondActivity 中接收:
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
String dataString = bundle.getString("data_string");
int dataInt = bundle.getInt("data_int");
char dataChar = bundle.getChar("data_char");
}
适合传递:
字符串
数字
布尔值
Parcelable 对象
Serializable 对象
不适合传递大量数据。
2. 不推荐滥用静态变量通信
可以用静态变量传少量临时数据:
public class DataHolder {
public static String username;
}
写入:
DataHolder.username = "张三";
读取:
String name = DataHolder.username;
但是不推荐大量使用,因为:
进程被杀后数据会丢
生命周期不安全
容易造成内存泄漏
数据来源不清晰
不适合跨进程
更推荐:
Intent
ViewModel
Repository
数据库
DataStore
SharedPreferences
3. Activity 与 Service 通信:绑定服务
如果 Activity 需要和 Service 长时间交互,可以使用绑定服务。
Service 中提供 Binder:
public class MyService extends Service {
private String data;
public class MyBinder extends Binder {
public void sendData(String value) {
data = value;
}
}
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
}
Activity 中绑定 Service:
private MyService.MyBinder binder;
private final ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binder = (MyService.MyBinder) service;
binder.sendData("来自 Activity 的数据");
}
@Override
public void onServiceDisconnected(ComponentName name) {
binder = null;
}
};
绑定:
Intent intent = new Intent(this, MyService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
解绑:
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(connection);
}
实际项目中要注意避免重复解绑,可以维护一个 bound 标记。
4. Activity 与 Service 通信:Intent 传值
如果只是启动 Service 时传少量参数,可以直接用 Intent。
原 PDF 示例中这里有一个明显错误:
startActivity(intent);
启动 Service 应该使用:
startService(intent);
正确示例:
Intent intent = new Intent(this, MyService.class);
intent.putExtra("data_string", "string数据");
startService(intent);
Service 中接收:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
String data = intent.getStringExtra("data_string");
}
return START_NOT_STICKY;
}
适合:
启动服务时传递参数
一次性命令
少量数据传递
5. 版本差异:Service 后台限制
Android 8.0 / API 26 之后,后台 Service 受到更多限制。
如果需要执行用户可感知的长期任务,应该考虑:
Foreground Service
WorkManager
JobScheduler
例如:
音乐播放
导航
录音
文件上传下载
定时同步
不要把长期后台任务简单理解为:
startService() 后就一直稳定运行
这在现代 Android 上不可靠。
6. Service 回调 Activity:Callback + Handler
如果 Service 中有耗时任务,任务完成后需要通知 Activity,可以使用:
Callback + Handler
基本思路:
Activity 绑定 Service
Activity 把 Callback 传给 Service
Service 执行任务
Service 通过 Callback 通知 Activity
Activity 用 Handler 切回主线程更新 UI
因为 Android 只能在主线程更新 UI,如果 Service 回调发生在子线程中,需要切回主线程:
handler.post(() -> {
// 更新 UI
});
或者使用:
LiveData
StateFlow
Broadcast
Messenger
AIDL
根据场景选择。
7. Activity 与 Fragment 通信:Bundle
Activity 创建 Fragment 时,可以通过 setArguments() 传递参数。
Activity 中:
Bundle bundle = new Bundle();
bundle.putString("data_string", "数据");
bundle.putInt("data_int", 10);
Fragment fragment = new MyFragment();
fragment.setArguments(bundle);
Fragment 中:
Bundle bundle = getArguments();
if (bundle != null) {
String data = bundle.getString("data_string");
int number = bundle.getInt("data_int");
}
这种方式适合 Fragment 初始化参数。
8. Activity 直接调用 Fragment 方法
Activity 也可以拿到 Fragment 引用后,直接调用它的方法:
MyFragment fragment = new MyFragment();
fragment.updateData("传递的数据");
Fragment 中:
public void updateData(String data) {
// 更新 Fragment 数据
}
但要注意生命周期。
如果 Fragment 还没 attach,或者 View 还没创建,直接更新 UI 可能会出问题。
更推荐的现代方式:
同一 Activity 内共享 ViewModel
Fragment Result API
接口回调
Navigation Component 参数传递
9. Scheme 跳转协议
Scheme 是一种页面跳转协议。
例如:
myapp://product/detail?id=100
它可以让外部页面或系统通知跳转到 App 内指定页面。
常见场景:
H5 页面打开 App 指定页面
通知栏点击跳转详情页
短信链接唤起 App
运营活动页跳转 App 内页
服务器下发跳转路径
10. Scheme 的基本配置
Manifest 中配置:
<activity android:name=".ProductDetailActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="myapp"
android:host="product"
android:path="/detail" />
</intent-filter>
</activity>
链接:
myapp://product/detail?id=100
Activity 中获取参数:
Uri uri = getIntent().getData();
if (uri != null) {
String id = uri.getQueryParameter("id");
}
11. Scheme 与 App Links 的区别
| 方式 | 特点 |
|---|---|
| 自定义 Scheme | 简单,容易接入,但可能被其他 App 抢占 |
| Android App Links | 基于 HTTPS 和域名验证,更适合生产环境外部链接跳转 |
简单理解:
内部约定跳转:Scheme 可以用
正式 Web 链接唤起 App:优先考虑 App Links
12. 总结
| 通信对象 | 推荐方式 |
|---|---|
| Activity → Activity | Intent / Bundle |
| Activity → Service | bindService / startService + Intent |
| Service → Activity | Callback + Handler / LiveData / Flow / Broadcast |
| Activity → Fragment | setArguments |
| Fragment → Activity | 共享 ViewModel / 接口回调 / Fragment Result API |
| 外部 → App 页面 | Scheme / App Links |
记忆口诀:
页面传页面,用 Intent。
页面传 Fragment,用 Arguments。
页面连 Service,用 Binder。
外部跳 App,用 Scheme 或 App Links。
参考来源
- 原始 PDF:《01、Activity知识总结.pdf》
- Android 官方文档:Activity 生命周期
https://developer.android.com/guide/components/activities/activity-lifecycle - Android 官方文档:Activity API Reference
https://developer.android.com/reference/android/app/Activity - Android 官方文档:处理配置变更
https://developer.android.com/guide/topics/resources/runtime-changes - Android 官方文档:
<activity>manifest 配置
https://developer.android.com/guide/topics/manifest/activity-element - Android 官方文档:Tasks and back stack
https://developer.android.com/guide/components/activities/tasks-and-back-stack - Android 官方文档:Services overview
https://developer.android.com/develop/background-work/services