Xamarin + MvvmCross + Azure 移动应用表请求不起作用

Posted

技术标签:

【中文标题】Xamarin + MvvmCross + Azure 移动应用表请求不起作用【英文标题】:Xamarin + MvvmCross + Azure Mobile App table request not working 【发布时间】:2018-08-26 14:44:13 【问题描述】:

我一直在构建一个简单的 Xamarin 应用程序,它使用 MvvmCross 框架和 Azure 移动应用程序服务来存储和检索云中的数据。 UI 项目是特定于平台的。

我的应用程序的主视图显示了一个帖子列表,这个列表应该是从 Azure 云中检索到的。 发生的情况是,在启动画面之后,应用程序只显示黑屏。 检索数据的调用似乎已正确触发,但从未收到响应。

这是我的帖子视图模型:

public class PostsViewModel : MvxViewModel
    
        readonly IPostService _postService;
        readonly IMvxNavigationService _navigationService;
        readonly MvxSubscriptionToken token;

        public PostsViewModel(IPostService postService, IMvxMessenger messenger, IMvxNavigationService navigationService)
        
            _postService = postService;
            _navigationService = navigationService;

            token = messenger.SubscribeOnMainThread<PostsChangedMessage>
                (async mex => await LoadPosts());

            Posts = new ObservableCollection<PostViewModel>();
            AddNewPostCommand = new MvxAsyncCommand(AddNewPost);
            ShowPostDetailsCommand = new MvxAsyncCommand<PostViewModel>(ShowPostDetails);
        

        #region Properties
        public ObservableCollection<PostViewModel> Posts  get; set; 

        private bool isLoading = true;
        public bool IsLoading
        
            get => isLoading;
            set => SetProperty(ref isLoading, value);
        
        #endregion

        #region Commands
        public IMvxAsyncCommand AddNewPostCommand  get; 
        private async Task AddNewPost()
        
            await _navigationService.Navigate(typeof(PostViewModel), new Post());
        

        public IMvxAsyncCommand<PostViewModel> ShowPostDetailsCommand  get; 
        private async Task ShowPostDetails(PostViewModel postViewModel)
        
            await _navigationService.Navigate(typeof(PostDetailsViewModel), postViewModel);
        
        #endregion

        #region Functions
        public override async Task Initialize()
        
            await LoadPosts();
        

        private async Task LoadPosts()
        
            // Remove all counters before reloading
            Posts.Clear();

            var posts = await _postService.GetAllPosts();
            foreach(var post in posts)
            
                var viewModel = new PostViewModel(_postService, _navigationService);
                viewModel.Prepare(post);
                Posts.Add(viewModel);
            

            IsLoading = false;
        
        #endregion
    

这是我的邮政服务:

    public class PostService : IPostService
    
        readonly IPostRepository _repository;
        readonly IMvxMessenger _messenger;

    public PostService(IPostRepository repository, IMvxMessenger messenger)
    
        _repository = repository;
        _messenger = messenger;
    

    public async Task<Post> AddNewPost(Post post)
    
        // Just for testing purposes
        post.Date = DateTimeOffset.Now;
        // Temporary hard-coded author; this will be get from the user object 
        post.Author = "John Smith";

        await _repository.Save(post).ConfigureAwait(false);
        _messenger.Publish(new PostsChangedMessage(this));

        return post;
    

    public async Task DeletePost(Post post)
    
        await _repository.Delete(post).ConfigureAwait(false);
        _messenger.Publish(new PostsChangedMessage(this));
    

    public Task<List<Post>> GetAllPosts()
    
        return _repository.GetAll();
    

这是我的仓库:

public class PostRepository : IPostRepository

    MobileServiceClient MobileService
        = new MobileServiceClient(@"https://vntestapp.azurewebsites.net", new LoggingHandler(true));

    IMobileServiceTable<Post> postTable;

public PostRepository()

    postTable = MobileService.GetTable<Post>();


public Task Delete(Post post)

    return postTable.DeleteAsync(post);


public async Task<List<Post>> GetAll()

    return await postTable.ToListAsync();


public async Task<Post> Save(Post post)

    await postTable.InsertAsync(post);
    return post;

【问题讨论】:

注释掉阻塞请求会发生什么,一切正常?运行平台是ios还是android?如果是 android 尝试调用 Task.Run() 中的 api 并查看它是否返回。 运行平台为安卓。在 Task.Run() 中调用 api 可以正常工作。怎么会这样?我不明白这个问题。我是否导致线程死锁? 我更新了这个作为答案,我会用正确的解释更新答案,现在,我认为你有好的:) 【参考方案1】:

如果运行平台是 android,则使用 Task.Run() 构造进行 API 调用。

根据我使用 Mvvmcross 的实际经验,有时在 android 中,async 方法中的等待调用会阻塞该线程并且它永远不会返回,

在这种情况下,如果您在 Task.Run() 中调用它,它就可以正常工作。 虽然 iOS 没有这个问题。

我会寻找更深层次的解释来提供原因。

【讨论】:

以上是关于Xamarin + MvvmCross + Azure 移动应用表请求不起作用的主要内容,如果未能解决你的问题,请参考以下文章

错误 UWP 与 mvvmcross + xamarin 形式

Xamarin + MvvmCross + Azure 移动应用表请求不起作用

MvvmCross、Xamarin Studio 和 ICommands

在 Xamarin.Android 中通过 MVVMCross 绑定 OxyPlot

TabbedPage 内的 xamarin mvvmcross TabbedPage

Xamarin Forms + Mvvmcross绑定命令不起作用