在不修改服务appA(appServer)的前提下,可以通过在appB(appClient)中调整Bundle的分页参数解决binder传输数据过大的问题。以下是具体方案:
解决方案核心思路
通过MediaBrowser的subscribe方法传递分页参数,控制每次请求的数据量(如每次100条),避免单次传输超过1000条数据导致binder失败。需在appB中实现分页逻辑,循环请求所有数据。
步骤详解
-
定义分页参数
在Bundle中添加分页控制键值,使用Android MediaSession的标准参数或自定义参数:Bundle requestBundle = new Bundle(); requestBundle.putInt(MediaConstants.EXTRA_PAGE, pageIndex); // 当前页码 requestBundle.putInt(MediaConstants.EXTRA_PAGE_SIZE, pageSize); // 每页数据量 -
设置合理的分页大小
根据binder传输上限(通常1MB),将pageSize设为安全值(例如100):private static final int SAFE_PAGE_SIZE = 100; // 单页最大数据量 -
分页请求数据
循环发送分页请求,直到获取全部数据:int currentPage = 0; boolean hasMoreData = true; List<MediaItem> allItems = new ArrayList<>(); while (hasMoreData) { Bundle bundle = new Bundle(); bundle.putInt(MediaConstants.EXTRA_PAGE, currentPage); bundle.putInt(MediaConstants.EXTRA_PAGE_SIZE, SAFE_PAGE_SIZE); mediaBrowser.subscribe(parentId, bundle, new SubscriptionCallback() { @Override public void onChildrenLoaded(String parentId, List<MediaItem> children) { allItems.addAll(children); if (children.size() < SAFE_PAGE_SIZE) { hasMoreData = false; // 已获取全部数据 } } }); currentPage++; } -
处理边界情况
- 超时处理:设置超时回调,避免网络异常导致无限等待。
- 错误重试:在
onError中实现重试机制(如指数退避)。 - 同步控制:使用
CountDownLatch或回调链确保分页请求顺序执行。
关键代码优化
// 分页请求封装方法
public void loadPaginatedData(String mediaId) {
AtomicInteger page = new AtomicInteger(0);
List<MediaItem> resultList = new ArrayList<>();
SubscriptionCallback callback = new SubscriptionCallback() {
@Override
public void onChildrenLoaded(String parentId, List<MediaItem> children) {
resultList.addAll(children);
if (children.size() == SAFE_PAGE_SIZE) {
// 继续请求下一页
requestNextPage(page.incrementAndGet());
} else {
// 全部数据加载完成
processFullData(resultList);
}
}
@Override
public void onError(String parentId) {
// 实现重试逻辑(最多3次)
if (retryCount < 3) {
requestNextPage(page.get());
}
}
};
requestNextPage(0); // 启动第一页请求
}
private void requestNextPage(int pageIndex) {
Bundle bundle = new Bundle();
bundle.putInt(MediaConstants.EXTRA_PAGE, pageIndex);
bundle.putInt(MediaConstants.EXTRA_PAGE_SIZE, SAFE_PAGE_SIZE);
mediaBrowser.subscribe(mediaId, bundle, callback);
}
注意事项
-
服务端兼容性
虽然appA未显式支持分页,但MediaSession框架会自动处理Bundle参数。需确保服务端能解析EXTRA_PAGE和EXTRA_PAGE_SIZE(标准Android常量,位于android.media.MediaConstants)。 -
性能平衡
- 增大
SAFE_PAGE_SIZE可减少请求次数,但需测试binder极限(建议200-500条)。 - 分页请求间隔建议≥300ms,避免服务端压力。
- 增大
-
数据一致性
在分页过程中若数据发生变化,建议:- 首次请求时获取数据版本号(如timestamp)
- 后续分页携带该版本号确保数据一致性
-
备用方案
若分页参数无效(服务端完全忽略),可改用MediaController.TransportControls.sendCustomAction()实现自定义分页协议,但需服务端配合(需基础包预留接口)。
重要提示:实际测试中需验证分页参数在服务端的有效性。若服务端完全不处理分页,需推动基础包升级或采用备用传输机制(如直接HTTP接口)。