AIDL使用观察者模式模拟股票报价、传感器数据
以下是一份基于AIDL观察者模式实现服务端数据自动变化并回调客户端的技术文档,采用Java实现,结合最佳实践和线程安全设计。:跨进程数据实时同步(如股票报价、传感器数据推送)1. 定义AIDL接口。3. 管理客户端回调。
·
以下是一份基于AIDL观察者模式实现服务端数据自动变化并回调客户端的技术文档,采用Java实现,结合最佳实践和线程安全设计。
AIDL观察者模式技术文档:服务端数据变化回调机制
适用场景:跨进程数据实时同步(如股票报价、传感器数据推送)
一、核心架构设计
二、实现步骤与代码
1. 定义数据模型(Parcelable)
// Stock.java
public class Stock implements Parcelable {
private String symbol;
private float price;
// Parcelable实现
protected Stock(Parcel in) {
symbol = in.readString();
price = in.readFloat();
}
public static final Creator<Stock> CREATOR = new Creator<Stock>() {
@Override public Stock createFromParcel(Parcel in) { return new Stock(in); }
@Override public Stock[] newArray(int size) { return new Stock[size]; }
};
@Override public void writeToParcel(Parcel dest, int flags) {
dest.writeString(symbol);
dest.writeFloat(price);
}
// Getters & Setters
}
2. 定义AIDL接口
- 回调接口 (
IStockCallback.aidl
)package com.example.stockservice; import com.example.stockservice.Stock; oneway interface IStockCallback { void onStockChanged(in Stock stock); // 单向非阻塞 }
- 服务接口 (
IStockService.aidl
)package com.example.stockservice; import com.example.stockservice.IStockCallback; interface IStockService { oneway void registerCallback(IStockCallback callback); // 注册 oneway void unregisterCallback(IStockCallback callback); // 注销 }
3. 服务端实现
// StockService.java
public class StockService extends Service {
private final RemoteCallbackList<IStockCallback> callbacks = new RemoteCallbackList<>();
private Stock currentStock = new Stock("AAPL", 150.0f);
private final Handler handler = new Handler(Looper.getMainLooper());
// 定时更新数据
private final Runnable updateTask = new Runnable() {
@Override public void run() {
currentStock.setPrice(140 + new Random().nextInt(20)); // 模拟价格波动
notifyClients(); // 通知所有客户端
handler.postDelayed(this, 10000); // 10秒间隔
}
};
private void notifyClients() {
int count = callbacks.beginBroadcast();
for (int i = 0; i < count; i++) {
try {
callbacks.getBroadcastItem(i).onStockChanged(currentStock);
} catch (RemoteException e) {
// 客户端进程终止时自动清理
}
}
callbacks.finishBroadcast();
}
private final IStockService.Stub binder = new IStockService.Stub() {
@Override
public void registerCallback(IStockCallback callback) {
callbacks.register(callback);
}
@Override
public void unregisterCallback(IStockCallback callback) {
callbacks.unregister(callback);
}
};
@Override
public void onCreate() {
super.onCreate();
handler.post(updateTask); // 启动定时任务
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
@Override
public void onDestroy() {
handler.removeCallbacks(updateTask);
callbacks.kill(); // 释放资源
super.onDestroy();
}
}
4. 客户端实现
// ClientActivity.java
public class ClientActivity extends AppCompatActivity implements IStockCallback {
private IStockService stockService;
private final ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
stockService = IStockService.Stub.asInterface(service);
try {
stockService.registerCallback(ClientActivity.this); // 注册回调
} catch (RemoteException e) { e.printStackTrace(); }
}
@Override
public void onServiceDisconnected(ComponentName name) {
stockService = null;
}
};
@Override
public void onStockChanged(Stock stock) {
runOnUiThread(() -> {
// 更新UI
textView.setText(String.format("%s: %.2f", stock.getSymbol(), stock.getPrice()));
});
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 绑定服务
Intent intent = new Intent();
intent.setComponent(new ComponentName(
"com.example.stockservice",
"com.example.stockservice.StockService"
));
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
if (stockService != null) {
try {
stockService.unregisterCallback(this);
} catch (RemoteException e) {
e.printStackTrace();
}
unbindService(conn);
}
super.onDestroy();
}
}
三、关键特性与优化
特性 | 实现方案 | 优势 |
---|---|---|
线程安全回调管理 | 使用 RemoteCallbackList |
自动处理客户端进程死亡导致的泄漏 |
非阻塞通知 | AIDL接口声明为 oneway |
避免服务端线程阻塞 |
跨进程数据传递 | 数据类实现 Parcelable |
高效序列化/反序列化 |
后台限制适配 | 服务端使用前台服务(需声明权限) | 兼容 Android 12+ 后台限制 |
四、常见问题排查
-
回调不触发
- 检查服务端是否用
RemoteCallbackList
而非ArrayList
(否则无法感知客户端死亡) - 确认客户端
onServiceConnected
中正确调用registerCallback()
- 检查服务端是否用
-
跨进程传递失败
- 确保所有自定义数据类型实现
Parcelable
- 验证 AIDL 文件中的包名和导入路径是否一致
- 确保所有自定义数据类型实现
-
服务绑定失败
- AndroidManifest 中声明服务并设置
exported="true"
<service android:name=".StockService" android:exported="true" android:permission="android.permission.FOREGROUND_SERVICE"/>
- AndroidManifest 中声明服务并设置
五、完整项目结构
├── app (客户端)
│ ├── src/main/java/com/example/client
│ │ ├── ClientActivity.java
│ └── AndroidManifest.xml
│
├── service (服务端)
│ ├── src/main/aidl/com/example/stockservice
│ │ ├── IStockCallback.aidl
│ │ └── IStockService.aidl
│ ├── src/main/java/com/example/stockservice
│ │ ├── Stock.java
│ │ └── StockService.java
│ └── AndroidManifest.xml
源码参考:AIDL回调机制详解 | RemoteCallbackList使用指南
更多推荐
所有评论(0)