【发布时间】:2015-06-26 16:11:55
【问题描述】:
我已经尝试过 Virgil Dobjanschi 模式 A 和 B 并得出我想使用模式 C 的结论,因为在这种情况下,我可以使用基于谷歌的代码,如果我有非稳定的网络连接等等... 但我没有找到如何以正确的方式实现这一点。 尤其是当您考虑到数据库足够大,可以每次都进行同步时。
我做了这样的事情
当 CursorLoader 执行查询以显示 BizInbox 查询返回游标并启动 SyncAdapter 它应该获取数据并停止其活动
但我的问题是 SyncAdatert 的 onPerformSync 再次启动。它看起来像无尽的循环 当光标重新加载其数据并启动 onPerformSync 等等... 并且 SyncAdapter 像我希望的那样在没有任何队列的情况下并行执行。
我应该注意到 REST 后端处理数据正确,并且执行 onPerformSync 的第二个请求没有数据,因为它使用了 If-Modified-Since http 标头。
很明显我做错了什么,因为我的 SyncAdapter 没有做同步退避并且没有结束地发出请求。
当我这样做的时候 if (!ContentResolver.isSyncActive(mConnectedAccount, Scheme.AUTHORITY)) { ContentResolver.requestSync( mConnectedAccount, // 同步账户 Scheme.AUTHORITY, // 内容权限 b); // 额外内容 } 别的 { Log.d(TAG, "> runSyncAdaterForClaimBizInbox 跳过启动适配器它已经处于活动状态"); }
我能够赢得问题,但问题仍然存在 如果需要同步部分数据 - 不是所有数据,如何执行此同步 ContentResolver.isSyncActive(mConnectedAccount, Scheme.AUTHORITY) - 此方法无法提供信息它正在同步的数据的哪一部分,并且由于某些原因我在这里没有队列。如何解决这个问题?
请帮我找出错误,或者可能有人有模式 C 可编译代码来找出如何正确实现这个模式。
提前致谢。
以下代码:
公共类 ContentProvider {
@Override
public Cursor query(final Uri uri, final String[] projection, final String selection, final String[] selectionArgs, final String sortOrder) {
final SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
final String orderBy = prepareQuery(uri, sortOrder, qb);
final SQLiteDatabase db = databaseHelper.getReadableDatabase();
final Cursor cursor = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);
runSyncAdapterForQuery(uri);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
void runSyncAdapterForQuery(Uri uri) {
switch (uriMatcher.match(uri)) {
case BIZ_INBOX:
runSyncAdaterForBizInbox(METHOD_GET);
break;
}
}
void runSyncAdaterForBizInbox(String method) {
Bundle b = new Bundle();
b.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
b.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
b.putString(METHOD_EXTRA, method);
b.putInt(RESOURCE_TYPE_EXTRA, RESOURCE_TYPE_BIZ_INBOX);
Account mConnectedAccount = new Account(BPalAccountGeneral.ACCOUNT_NAME, BPalAccountGeneral.ACCOUNT_TYPE);
//if (!ContentResolver.isSyncActive(mConnectedAccount, Scheme.AUTHORITY)) { Do i need this ? Where is Sync Adapters queue ?
ContentResolver.requestSync(
mConnectedAccount, // Sync account
Scheme.AUTHORITY, // Content authority
b); // Extras
//}
}
}
SyncAdapter
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
String accessToken = "some_token";
switch (resourceType) {
case UNKNOWN_RESOURCE_TYPE:
//do update all ...
break;
case RESOURCE_TYPE_BIZ_INBOX:
if (method.equals(METHOD_GET)) {
String url = "some_inbox_url"
GetBizInboxRequest request = new GetBizInboxRequest();
BizInboxDAO BizInboxDAO = new BizInboxDAO();
String lastModified = BizInboxDAO.getLastModified(getContext().getContentResolver());
RestMethodResult<RestListEntityContainer<BizInboxEntity>> restMethodResult =
request.getBizInboxItems(
url,
null,
lastModified,
accessToken);
int statusCode = restMethodResult.getStatusCode();
if (statusCode == MobileConstant.HTTP_OK) {
List<BizInboxEntity> serverBizInboxEntities = restMethodResult.getResource().getList();
for (BizInboxEntity entity : serverBizInboxEntities) {
BizInboxDAO.insertyData(getContext().getContentResolver(), entity);
syncResult.stats.numInserts++;
}
if(syncResult.stats.numInserts > 0) {
Log.d(TAG, "> onPerformSync BizInboxDAO.sendNotification ");
BizInboxDAO.sendNotification(getContext().getContentResolver());
}
} else {
syncResult.stats.numIoExceptions++;
syncResult.databaseError = true;
}
}
break;
default:
break;
}
}
【问题讨论】:
-
谢尔盖,很难读懂你的问题,也不清楚你在问什么。此外,在引用某些内容时(Google IO 上的一次演讲),最好添加一个链接。如果您的问题一开始很难阅读,人们不太可能去寻找该链接。
-
对不起,我写的有点情绪化:-)。主要问题是:什么是使用模式 C 的好例子。同时使用 Sync Adapter 和 Content Provider 的正确方法是什么。感谢您的有用评论。