I do async call from viewmodel, so I started to use Nito.Mvvm.NotifyTask class. It works good except one, that my async method calls two times. I'm not 100% sure that it is because of this, but I don't have any another ideas.
ViewModel:
public class NewsPageViewModel : BindableBase { private INavigationService _navigationService; private readonly Session _session; public NotifyTask<ObservableCollection<PrivateNewsModel>> PrivateNews { get; } private readonly PrivateNewsManager _privateNewsManager; public NewsPageViewModel(INavigationService navigationService, ISecuredDataProvider securedDataProvider) { _navigationService = navigationService; var store = securedDataProvider.Retreive(ConstantsService.ProviderName, UserManager.GetLastUser()); _session = new Session(UserManager.GetLastUser(), store.Properties.First().Value, store.Properties["PrivateFeedUrl"]); var navigationParameters = new NavigationParameters { { "Session", _session } }; _privateNewsManager = new PrivateNewsManager(_session); PrivateNews = NotifyTask.Create(GetPrivateNewsAsync()); } private async Task<ObservableCollection<PrivateNewsModel>> GetPrivateNewsAsync() { return new ObservableCollection<PrivateNewsModel> (await _privateNewsManager.GetPrivateNews()); } }
async methods :
public async Task<IEnumerable<PrivateNewsModel>> GetPrivateNews() { try { var gitHubPrivateFeedItems = await GetPrivateFeedItems(); var gitRemotePrivateFeedItems = new List<PrivateNewsModel>(); foreach ( var item in gitHubPrivateFeedItems ) { var newsItem = new PrivateNewsModel { Title = item?.Element(XName.Get("title", ConstantsService.AtomNamespace))?.Value, Published = TimeService.ConvertToFriendly(item?.Element(XName.Get("published", ConstantsService.AtomNamespace))?.Value), ImageUrl = item?.Element(XName.Get("media", ConstantsService.AtomNamespace))?.Attribute(XName.Get("url", ConstantsService.AtomNamespace)).Value }; var splitedTitle = newsItem.Title?.Split(''); if ( splitedTitle != null ) { newsItem.Perfomer = splitedTitle[0]; newsItem.ActionType = splitedTitle[1]; newsItem.AdditionalTarget = newsItem.ActionType == "added" ? splitedTitle[2] : string.Empty; newsItem.Target = splitedTitle[splitedTitle.Length - 1]; } gitRemotePrivateFeedItems.Add(newsItem); } return gitRemotePrivateFeedItems; } catch ( WebException ex ) { throw new Exception("Something wrong with internet connection, try to On Internet "+ ex.Message); } catch ( Exception ex ) { throw new Exception("Getting repos from github failed! "+ ex.Message); } } private async Task<IEnumerable<XElement>> GetPrivateFeedItems() { var client = new HttpClient(new NativeMessageHandler()); var feed = await client.GetStringAsync(_session.GetPrivateFeedUrl()); if ( string.IsNullOrEmpty(feed) ) return new List<XElement>(); var parsedFeed = XElement.Parse(feed); var entries = from entry in parsedFeed.Elements("{"+ ConstantsService.AtomNamespace +"}entry") select entry; return entries; }
With breakpoint I see that It is passing like :ViewModel NotifyTask.Create -> ViewModel GetPrivateNewsAsync -> GetPrivateNews await GetPrivateFeedItems -> GetPrivateFeedItems await GetStringAsync . Then I think it waits for GetStringAsync finish and but because it didn't finish, it is doing the same that I wrote above. And when it did above job, then GetStringAsync already finished and it is doing foreach loop and others things. But when loop ended and I returned from GetPrivateNews, it is finishing GetPrivateNewsAsync and goes to GetPrivateFeedItems (but now it starts after line with await) and to foreach loop in GetPrivateNews (same after await). Then dones with this method and goes to GetPrivateNewsAsync in viewmodel(to the end of it) and now it finished.
Sorry for Name Convention. I will fix this.