为 Xamarin.Android 移动应用启用脱机同步

概述

本教程介绍适用于 Xamarin.Android 的 Azure 移动应用的脱机同步功能。 脱机同步允许最终用户与移动应用进行交互-查看、添加或修改数据,即使没有网络连接也是如此。 更改存储在本地数据库中。 设备重新联机后,这些更改将与远程服务同步。

在本教程中,你将从教程 “创建 Xamarin Android 应用 ”更新客户端项目,以支持 Azure 移动应用的脱机功能。 如果不使用下载的快速入门服务器项目,则必须将数据访问扩展包添加到项目中。 有关服务器扩展包的详细信息,请参阅 使用适用于 Azure 移动应用的 .NET 后端服务器 SDK

若要了解有关脱机同步功能的详细信息,请参阅 Azure 移动应用中的脱机数据同步主题。

更新客户端应用以支持脱机功能

Azure 移动应用脱机功能允许你在脱机方案中与本地数据库交互。 若要在应用中使用这些功能,请将 SyncContext 初始化为本地存储。 然后通过接口IMobileServiceSyncTable引用您的表。 SQLite 用作设备上的本地存储。

  1. 在 Visual Studio 中,在 创建 Xamarin Android 应用 教程中完成的项目中打开 NuGet 包管理器。 搜索并安装 Microsoft.Azure.Mobile.Client.SQLiteStore NuGet 包。
  2. 打开ToDoActivity.cs文件并取消注释 #define OFFLINE_SYNC_ENABLED 定义。
  3. 在 Visual Studio 中,按 F5 键重新生成并运行客户端应用。 应用的工作方式与启用脱机同步之前的工作方式相同。但是,本地数据库现在填充了可在脱机方案中使用的数据。

更新应用以断开与后端的连接

在本部分中,将中断与移动应用后端的连接,以模拟脱机情况。 添加数据项时,异常处理程序会告知应用处于脱机模式。 在此状态下,新增项被添加到本地商店,并在连接状态下执行推送时同步到移动应用程序的后端。

  1. 在共享项目中编辑ToDoActivity.cs。 将 applicationURL 更改为指向无效 URL:

      const string applicationURL = @"https://your-service.azurewebsites.fail";
    

    还可以通过在设备上禁用 wifi 和手机网络或使用飞行模式来演示脱机行为。

  2. F5 生成并运行应用。 请注意,应用启动后刷新时同步失败。

  3. 输入新项并注意到每次单击“ 保存”时推送失败并出现 [CancelledByNetworkError] 状态。 但是,新的待办事项存在于应用的本地存储中,直到可以同步到移动应用后端。 在生产应用中,如果取消这些异常,客户端应用的行为就像它仍然连接到移动应用后端一样。

  4. 关闭应用并重启它,以验证你创建的新项是否持久保存到本地存储中。

  5. (可选)在 Visual Studio 中,打开 服务器资源管理器。 导航到您的 Azure SQL 数据库 ->。 右键单击数据库并选择 “在 SQL Server 对象资源管理器中打开”。 现在可以浏览到 SQL 数据库表及其内容。 验证后端数据库中的数据没有改变。

  6. (可选)使用 REST 工具(如 Fiddler 或 Postman)通过表单 https://<your-mobile-app-backend-name>.azurewebsites.net/tables/TodoItem中的 GET 查询来查询移动后端。

更新应用以重新连接移动应用后端

在本部分中,将应用重新连接到移动应用后端。 首次运行应用程序时, OnCreate 事件处理程序将调用 OnRefreshItemsSelected。 此方法调用 SyncAsync 将本地存储与后端数据库同步。

  1. 在共享项目中打开ToDoActivity.cs,并还原 applicationURL 属性的更改。

  2. F5 键重新生成并运行应用。 当OnRefreshItemsSelected 方法执行时,应用程序使用推送和拉取操作将本地修改与 Azure 移动应用后端同步。

  3. (可选)使用 SQL Server 对象资源管理器或 REST 工具(如 Fiddler)查看更新的数据。 请注意,数据已在 Azure 移动应用后端数据库和本地存储之间同步。

  4. 在应用中,点击几个项目旁边的复选框,以便在当地商店完成这些操作。

    CheckItem 调用 SyncAsync 以将每个已完成的项与移动应用后端同步。 SyncAsync 同时调用推送和拉取功能。 每当对客户端已修改的表执行拉取操作时,系统始终会自动执行推送。 这可确保本地存储中的所有表及其关系保持一致性。 此行为可能会导致意外的推动。 有关此行为的详细信息,请参阅 Azure 移动应用中的脱机数据同步

查看客户端同步代码

完成教程“ 创建 Xamarin Android 应用 ”时下载的 Xamarin 客户端项目已包含支持使用本地 SQLite 数据库进行脱机同步的代码。 下面简要概述了教程代码中已包含的内容。 有关该功能的概念性概述,请参阅 Azure 移动应用中的脱机数据同步

  • 在执行任何表操作之前,必须初始化本地存储。 本地商店数据库在ToDoActivity.OnCreate()执行ToDoActivity.InitLocalStoreAsync()时初始化。 此方法使用 MobileServiceSQLiteStore Azure 移动应用客户端 SDK 提供的类创建本地 SQLite 数据库。

    此方法 DefineTable 在本地存储中创建一个表,该表与所提供的类型中的字段匹配, ToDoItem 在本例中。 该类型不必包括远程数据库中的所有列。 可以只存储列的子集。

      // ToDoActivity.cs
      private async Task InitLocalStoreAsync()
      {
          // new code to initialize the SQLite store
          string path = Path.Combine(System.Environment
              .GetFolderPath(System.Environment.SpecialFolder.Personal), localDbFilename);
    
          if (!File.Exists(path))
          {
              File.Create(path).Dispose();
          }
    
          var store = new MobileServiceSQLiteStore(path);
          store.DefineTable<ToDoItem>();
    
          // Uses the default conflict handler, which fails on conflict
          // To use a different conflict handler, pass a parameter to InitializeAsync.
          // For more details, see https://go.microsoft.com/fwlink/?LinkId=521416.
          await client.SyncContext.InitializeAsync(store);
      }
    
  • toDoTable的成员ToDoActivityIMobileServiceSyncTable类型,而不是IMobileServiceTable。 IMobileServiceSyncTable 将所有创建、读取、更新和删除(CRUD)表操作指向本地存储数据库。

    通过调用 IMobileServiceSyncContext.PushAsync()决定何时将更改推送到 Azure 移动应用后端。 同步上下文通过跟踪和推送客户端应用在调用 PushAsync 时修改的所有表中的更改来帮助保留表关系。

    每当刷新 todoitem 列表或添加或完成 todoitem 时,提供的代码将调用 ToDoActivity.SyncAsync() 同步。 代码在每个本地更改后同步。

    在提供的代码中,查询远程 TodoItem 表中的所有记录,但也可以通过将查询 ID 和查询传递给 PushAsync来筛选记录。 有关详细信息,请参阅 Azure 移动应用中脱机数据同步中的增量同步部分。

      // ToDoActivity.cs
      private async Task SyncAsync()
      {
          try {
              await client.SyncContext.PushAsync();
              await toDoTable.PullAsync("allTodoItems", toDoTable.CreateQuery()); // query ID is used for incremental sync
          } catch (Java.Net.MalformedURLException) {
              CreateAndShowDialog (new Exception ("There was an error creating the Mobile Service. Verify the URL"), "Error");
          } catch (Exception e) {
              CreateAndShowDialog (e, "Error");
          }
      }
    

其他资源