【问题标题】:Using ContentResolver instead of ContentProviderClient in SyncAdapter在 SyncAdapter 中使用 ContentResolver 而不是 ContentProviderClient
【发布时间】:2014-03-31 20:51:07
【问题描述】:

据我了解,在 SyncService 中定义的一个 SyncAdapter 仅限于接收一个 ContentProvider 权限来处理。

但是,与此同时,它可以访问 ContentResolver,它还允许在其他 ContentProvider 上运行查询。如果需要开发人员向 SyncAdapter 提供单一的内容权限,并且她可以在她有权访问的任何 ContentProvider 上做任何她想做的事情,我不理解这个特定的设计概念。我的问题是:忽略 onPerformSync 的参数:字符串权限和 ContentProviderClient 提供程序并使用纯 ContentResolver 会有什么后果?

我的应用程序(实际上是它的 SyncService)的想法很简单:查询日历服务器(在我的例子中是 OwnCloud)不仅可以获取事件(与 com.android.calendar 同步),还可以获取 VTODOS,它然后分布在各种任务管理应用程序之间,我可以获得源代码和/或 ContentProviderContract。我还想到了自己的“Hub”ContentProvider,它具有基本的 VTODO/Task 结构,与服务器相比是唯一的。它应该能够与任务管理应用程序的不同内容提供商进行双向同步,然后与服务器同步。

我已阅读using ContentProviderClient vs ContentResolver to access content provider,我想我理解其中的区别。我现在很困惑,为什么 android SDK 强烈建议在单个 SyncAdapter 中使用单个 ContentProvider,而您却可以使用 ContentResolver 来绕过该限制。

我花了一整天的时间来解决这个问题,并搜索了数百个关于这个问题的 SO/Google 资源(其中一些资源多次)。我还看到了有关使用一个 SyncAdapter 同步多个 ContentProvider 的问题,但没有一个答案接近建议使用 ContentResolver。

【问题讨论】:

    标签: android android-contentprovider android-contentresolver android-syncadapter


    【解决方案1】:

    SyncAdapter 的上下文中使用ContentResolver 的API 没有特殊限制。恕我直言,框架将ContentProviderClientauthority 传递给onPerformSync() 的唯一原因是方便,并且可以向开发人员提示SyncAdapter 的预期工作方式。

    这一事实在AbstractThreadedSyncAdapter.SyncThread 的源代码中很容易看出——传递给onPerformSync()ContentProviderClient 是以标准方式获得的:

        @Override
        public void run() {
            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    
            // Trace this sync instance.  Note, conceptually this should be in
            // SyncStorageEngine.insertStartSyncEvent(), but the trace functions require unique
            // threads in order to track overlapping operations, so we'll do it here for now.
            Trace.traceBegin(Trace.TRACE_TAG_SYNC_MANAGER, mAuthority);
    
            SyncResult syncResult = new SyncResult();
            ContentProviderClient provider = null;
            try {
                if (isCanceled()) {
                    return;
                }
                provider = mContext.getContentResolver().acquireContentProviderClient(mAuthority);
                if (provider != null) {
                    AbstractThreadedSyncAdapter.this.onPerformSync(mAccount, mExtras,
                            mAuthority, provider, syncResult);
                } else {
                    syncResult.databaseError = true;
                }
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_SYNC_MANAGER);
    
                if (provider != null) {
                    provider.release();
                }
                if (!isCanceled()) {
                    mSyncContext.onFinished(syncResult);
                }
                // synchronize so that the assignment will be seen by other threads
                // that also synchronize accesses to mSyncThreads
                synchronized (mSyncThreadLock) {
                    mSyncThreads.remove(mThreadsKey);
                }
            }
        }
    

    因此,bootom 行:您可以根据需要在SyncAdapter 中使用ContentResolver - 只需调用getContext().getContentResolver() 并访问任何导出的ContentProvider

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-11
      • 1970-01-01
      • 2018-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多