【问题标题】:Syncing with server与服务器同步
【发布时间】:2023-04-10 02:27:01
【问题描述】:

我已经为 Android 开发了一段时间,目前正在与我的服务器同步。
快速介绍:我读过 Sync Adapter 并且知道它的作用,但我只是想知道它是否是我的最佳选择。

在我的应用中,用户可以点击一个按钮来通知对他来说很重要的事情。单击时,我想更新服务器以保留数据,并通知他的亲戚。我的问题如下:用户可以多次单击该按钮来打开和关闭它,因此在这种情况下,我不想在每次用户单击按钮时都打开与服务器的通信,它甚至可能不会从它以前的状态。

所以我的问题是:同步适配器对我来说是正确的吗,还是我应该建立自己的类来与服务器对话,服务器会检查它,并像 Volley 那样接收紧急\非紧急的。 如果有人能澄清 Sync Adapter 的确切工作,我将不胜感激(它是否符合我所说的?)

如果有不清楚的地方,我很乐意澄清。 提前致谢。

【问题讨论】:

    标签: android android-syncadapter server-communication


    【解决方案1】:

    Android 同步框架应该非常适合您使用。如果您根据需要标记同步,系统将不会立即启动它,而是会延迟一小段时间。这样,如果用户切换回按钮,您将能够注意到值没有改变。旁注:如果您使用ContentProvider,它会在数据更改时自动通知SyncAdapter。如果需要,您还可以手动触发同步。

    同步框架所做的只是调用一个方法 (onPerformSync)。您可以随意实现它。如果您认为最后一个太接近了,您可以跳过同步,或者查找数据是否真的发生了变化,或者它恢复到原始值(例如,您可以将“最后同步”的值保留在数据库中,然后您可以比较它onPerformSync 方法中的当前值。如果相同,则无需更改。

    奖励:您将节省电池电量,因为同步框架会尽可能按顺序运行多个同步,您的用户将能够在一个集中的位置管理他们的帐户(Android 设置),禁用系统范围内的同步(想想 Sony 的耐力模式,将每个 SyncAdapter 设置为在活动时暂停)。

    【讨论】:

    【解决方案2】:

    您也可以采取另一种方法,从您的服务器推送到设备,您的应用不必不时要求更新,而是由服务器告诉“嘿,我有东西要给你” .

    看看谷歌云消息传递。另一方面,如果您更喜欢用户应该专门要求其更新的方法,那么您实际上不需要担心同步适配器 - 当然,这取决于您的应用程序的要求。

    不过,我还是建议你看看 GCM,它更简洁、更优雅,让服务器通知然后继续询问。

    【讨论】:

    • 我正在使用 GCM 进行通知。我目前正在询问有关更新我更改了某些内容的服务器。不更新
    • 哦,好吧,我误会了;这应该很简单,只需在特定操作完成后立即向服务器发送通知,说明发生了什么事情;该应用程序是否也应该处理离线情况?还是您必须在离线时保留一些数据?
    • 请阅读这个问题,我不想每次用户做某事时都打开 http 套接字,因为就像我描述的那样,他可能只是多次点击打开/关闭同一个按钮数据甚至可能不会改变。
    • 当用户采取行动时,在本地保持该行动,这样您也可以覆盖离线情况。你不应该打开一个套接字或做任何 http 请求,除非有一些东西存储在本地,当然——在你将数据发送到服务器之后,你在本地清除它。
    • 如果您使用 SyncAdapter,在绑定到 SyncAdapter 的 ContentProvider 中存储数据将自动触发挂起同步。根据上次同步时间,它将立即启动或等待片刻。每分钟触发两次自动同步的次数不会超过一次。
    【解决方案3】:

    当设备上的数据发生变化时运行同步适配器。此选项允许您将修改后的数据从设备发送到服务器,如果您需要确保服务器始终拥有最新的设备数据,该选项尤其有用。如果您实际上将数据存储在内容提供程序中,则此选项很容易实现。如果您使用的是存根内容提供程序,则检测数据更改可能会更加困难。

    运行同步适配器以响应用户操作。但是,要提供最佳用户体验,您应该主要依靠自动化程度更高的选项之一。

    您可以通过设置运行之间的等待时间或在一天中的特定时间运行它,或两者兼而有之,定期运行同步适配器。定期运行同步适配器可以让您大致匹配服务器的更新间隔。

    【讨论】:

      【解决方案4】:

      在内容提供程序数据更改时运行同步适配器

      public class MainActivity extends FragmentActivity {
      ...
      // Constants
      // Content provider scheme
      public static final String SCHEME = "content://";
      // Content provider authority
      public static final String AUTHORITY = "com.example.android.datasync.provider";
      // Path for the content provider table
      public static final String TABLE_PATH = "data_table";
      // Account
      public static final String ACCOUNT = "default_account";
      // Global variables
      // A content URI for the content provider's data table
      Uri mUri;
      // A content resolver for accessing the provider
      ContentResolver mResolver;
      ...
      public class TableObserver extends ContentObserver {
          /*
           * Define a method that's called when data in the
           * observed content provider changes.
           * This method signature is provided for compatibility with
           * older platforms.
           */
          @Override
          public void onChange(boolean selfChange) {
              /*
               * Invoke the method signature available as of
               * Android platform version 4.1, with a null URI.
               */
              onChange(selfChange, null);
          }
          /*
           * Define a method that's called when data in the
           * observed content provider changes.
           */
          @Override
          public void onChange(boolean selfChange, Uri changeUri) {
              /*
               * Ask the framework to run your sync adapter.
               * To maintain backward compatibility, assume that
               * changeUri is null.
              ContentResolver.requestSync(ACCOUNT, AUTHORITY, null);
          }
          ...
      }
      ...
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          ...
          // Get the content resolver object for your app
          mResolver = getContentResolver();
          // Construct a URI that points to the content provider data table
          mUri = new Uri.Builder()
                    .scheme(SCHEME)
                    .authority(AUTHORITY)
                    .path(TABLE_PATH)
                    .build();
          /*
           * Create a content observer object.
           * Its code does not mutate the provider, so set
           * selfChange to "false"
           */
          TableObserver observer = new TableObserver(false);
          /*
           * Register the observer for the data table. The table's path
           * and any of its subpaths trigger the observer.
           */
          mResolver.registerContentObserver(mUri, true, observer);
          ...
      }
      ...
      

      }

      【讨论】:

      • 你能解释一下你宣布的决赛吗?
      • 这些变量用于创建 uri。 new Uri.Builder() .scheme(SCHEME) .authority(AUTHORITY) .path(TABLE_PATH) .build();
      • 请注意,如果您将 SyncAdapter 绑定到 ContentProvider(假设您只想观察一个提供者),则不需要所有这些。您可以在sync-adapter XML 中将它们与android:contentAuthority 属性绑定。每次您的 ContentProvider 通知其观察者时,都会触发挂起的同步。
      猜你喜欢
      • 2019-01-16
      • 1970-01-01
      • 1970-01-01
      • 2013-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多