I develop Windows Phone App with Prism
framework (MVVM).
I use data caching. To get data I use proxy service. Proxy service creates two tasks
:
- the first task is receiving data from a web service and update data in local database (
SqLite
). - the second task is receiving data from the local database.
The ViewModel launches tasks
and displays data on UI.
It works, but I think it can be done much better. Any ideas?
ViewModel
public class UserProfilePageViewModel : ViewModel, IUserProfilePageViewModel
{
private readonly IUserServiceProxy _userServiceProxy;
private IUserItemViewModel _userProfile;
public IUserItemViewModel UserProfile
{
get { return _userProfile; }
set { SetProperty(ref _userProfile, value); }
}
public UserProfilePageViewModel(IUserServiceProxy userServiceProxy)
{
if (userServiceProxy == null) { throw new ArgumentNullException("The userServiceProxy can't be null"); }
_userServiceProxy = userServiceProxy;
}
public async override void OnNavigatedTo(object navigationParameter, Windows.UI.Xaml.Navigation.NavigationMode navigationMode, Dictionary<string, object> viewModelState)
{
_userId = navigationParameter as string;
await Load(navigationParameter as string);
}
public async Task Load(string id)
{
var taskList = _userServiceProxy.GetUserTaskList(id);
while (taskList.Count > 0)
{
var t = await Task.WhenAny(taskList);
taskList.Remove(t);
try
{
var result = await t;
//update UI
UserProfile.Model = result.Result;
}
catch (OperationCanceledException) { }
catch (Exception) { }
}
await Task<User>.WhenAll(taskList);
}
}
ServiceProxy
public class UserServiceProxy : IUserServiceProxy
{
private readonly IUserApi _userApi;
private readonly IUserRepository _userRepository;
private readonly IUserSettings _userSettings;
private readonly IAuthService _authService;
public UserServiceProxy(IUserApi userApi, IUserRepository userRepository, IUserSettings userSettings, IAuthService authService)
{
if (userApi == null) { throw new ArgumentNullException("The userApi can't be null"); }
if (userRepository == null) { throw new ArgumentNullException("The userRepository can't be null"); }
if (userSettings == null) { throw new ArgumentNullException("The settings can't be null"); }
if (authService == null) { throw new ArgumentNullException("The authService can't be null"); }
_userApi = userApi;
_userRepository = userRepository;
_userSettings = userSettings;
_authService = authService;
}
public List<Task<ResponseWrapper<User>>> GetUserTaskList(string id, CancellationToken cancellationTokenSource = new CancellationToken())
{
Func<Task<ResponseWrapper<User>>> getFromWeb = async () =>
{
var poco = await _userApi.GetAsync(id, cancellationTokenSource);
await _userRepository.MergeUser(LocalSQLite.Models.User.FromPoco(poco.Result));
return poco;
};
Task<Task<ResponseWrapper<User>>> outerTaskWeb = Task.Factory.StartNew(getFromWeb);
Task<ResponseWrapper<User>> innerTaskWeb = outerTaskWeb.Unwrap();
Func<Task<ResponseWrapper<User>>> getFromLocal = async () =>
{
var localUser = await _userRepository.LoadByUserIdAsync(id);
if (localUser == null) localUser = new LocalSQLite.Models.User();
return Models.WebApi.ResponseWrapper<Models.User.User>.Wrap(localUser.ToPoco());
};
Task<Task<ResponseWrapper<User>>> outerTaskLocal = Task.Factory.StartNew(getFromLocal);
Task<ResponseWrapper<User>> innerTaskLocal = outerTaskLocal.Unwrap();
List<Task<ResponseWrapper<User>>> tasks = new List<Task<ResponseWrapper<User>>>()
{
innerTaskWeb,
innerTaskLocal
};
return tasks;
}
}