Reputation: 401
I'm in the planning stage of a new Xamarin Forms app.
I would like the application to be offline first.
By this, I mean that the data should be read from/written to a local data store. And then, as soon as there is connectivity (that could be immediately or a few hours later) data is synced between local data store and the cloud.
What I'm looking for is a standard design pattern. I've found a few articles on the subject but ost are about a proprietary solution.
This article seems to be a very good start but it's not really about offline-first. Does anybody know about some good literature on the offline-first subject applied to Xamarin Forms, or at least .Net.
Many thanks for your time and answers, Julien
Upvotes: 3
Views: 3529
Reputation: 5799
You can achieve your offline/online data syncing with either the Microsoft Azure Mobile Client or with Realm. Realm makes a big point that they are all about offline first. While the Azure Mobile Client is largely about your main database is up in the cloud with an ability to cache that data locally to make your CRUD operations while you're offline which can then sync with your backend once you're back online.
You can learn more about Realm here
You can learn more about using the Azure Mobile Client here
Upvotes: 0
Reputation: 47417
It's a pretty loaded question, but in short, the way I've done it in the past is to use a shared IService
with all of the logic in a shared library.
This library lives in the mobile app and the API, and is responsible for handling the sync. The api will have the concrete implementation (to your repo) and the mobile app will have both the concrete implementation (to Sqlite) AND ALSO a proxy implementation with HttpClient
.
with regards to the REPO, you'll have one for mobile and one for the server and again share the same IRepo
note: use GUID's for all identifiers, never auto-incrementing, or you'll get collisions
example
// everything in here lives in a shared library that the server and mobile have access to.
public interface IUserRepository {
// shared methods to talk to data
}
public interface IUserService {
UserDto GetUserById(Guid userId);
IList<UserDto> FindUsers(int skip, int take);
void DeleteUserById(Guid userId);
// etc
}
public class UserService : IUserService {
public UserService (IUserRepository userRepo) {
_userRepo = userRepo;
}
}
public class UserProxyService : IUserService {
public UserProxyService (HttpClient httpClient) {
_httpClient = httpClient; // don't dispose... make singleton
}
}
// server implementation of the repo
public namespace MyApp.Api.Data {
public class UserRepository : IUserRepository {
// sql server calls (EF maybe)
}
}
// mobile implementation of the repo
public namespace MyApp.Mobile.Data { /* (portable) */
public class UserRepository : IUserRepository {
// sqlite calls on the phone
}
}
As for handling the sync. My recommendation would be to to push your changes immediately when possible, and probably OnResume
when previous attempts failed due to network issues. The reason I recommend doing it immediately is because the user will expect to see that data everywhere.
Upvotes: 1