Xamarin形成android json - 异步调用挂起/永不返回

时间:2016-06-03 14:48:29

标签: c# json xamarin.android xamarin.forms

您好我正在使用Xamarin表单中的Android应用程序从服务获取json数据并且它应该在ContactInfo类中显示该数据但是当您单击应该获得的按钮时那些数据然后显示它,然后带你到它挂起的ContactInfo类,一分钟后我的Galaxy s7告诉我应用程序没有响应你想要关闭吗? 我不知道我做错了什么

这是我的Xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ReadyMo.ContactInfo">
              <ListView ItemsSource="{Binding ContactInfoList}" HasUnevenRows="true">
               <ListView.ItemTemplate>
      <DataTemplate>
        <ViewCell>
          <Frame Padding="0,0,0,8" BackgroundColor="#d2d5d7">
            <Frame.Content>
              <Frame Padding="15,15,15,15"   OutlineColor="Gray" BackgroundColor="White">
                <Frame.Content>
                  <StackLayout Padding="20,0,0,0"  Orientation="Horizontal" HorizontalOptions="CenterAndExpand">
                    <Label x:Name="FirstName" Text="{Binding First_Name}" HorizontalOptions="Center">
                        </Label>
                        <Label x:Name ="LastName" Text="{Binding Last_Name}" HorizontalOptions="Center">
                        </Label>
                        <Label x:Name="County" Text="{Binding name}" HorizontalOptions="Center">
                        </Label>
                        <Label x:Name ="Adress" Text="{Binding Address1}" HorizontalOptions="Center">
                        </Label>
                          <Label x:Name ="City" Text="{Binding Address2}" HorizontalOptions="Center">
                        </Label>
                        <Label x:Name="Number"  Text="{Binding BusinessPhone}" HorizontalOptions="Center">
                        </Label>   
                  </StackLayout>
                </Frame.Content>
              </Frame>
            </Frame.Content>
          </Frame>
        </ViewCell>
      </DataTemplate>
    </ListView.ItemTemplate>
  </ListView>
</ContentPage>

这是我的代码隐藏:

using Newtonsoft.Json;
using ReadyMo.Data;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;

using Xamarin.Forms;

namespace ReadyMo
{
    public partial class ContactInfo : ContentPage
    {
        private County item;


        public static async Task<string> GetContactString(string contactid)
        {

            HttpClient client = new HttpClient();
            var url = $"http://sema.dps.mo.gov/county/service.php?id={contactid}";
            var response = await client.GetAsync(url);
            if (response.IsSuccessStatusCode)
            {
                var responsetext = await response.Content.ReadAsStringAsync();
                return responsetext;
            }
            throw new Exception(response.ReasonPhrase);


        }

        public ContactInfo()
        {
            InitializeComponent();

        }
        List <ContactInfoModel> ContactInfoList;
        public ContactInfo(County item)
        {
            InitializeComponent();
            this.item = item;

            var contactpagetext = ContactManager.GetContactString(item.id);
            var contact = GetContactString("001").Result;
            //need to add update database code 

            //Convert Jason string to object

             ContactInfoList = JsonConvert.DeserializeObject<List<ContactInfoModel>>(contact);
             this.BindingContext = ContactInfoList;





            //Floodplain Administrators



        }
    }
}

任何帮助都会很棒!

提前感谢!

2 个答案:

答案 0 :(得分:2)

你的问题在这一行:

var contact = GetContactString("001").Result;

causing a deadlock我在博客上全面解释。

要解决此问题,您必须首先意识到UI必须立即显示 。操作系统调用您的代码时,您无法等待HTTP请求在响应之前完成;这根本不被允许。

可以做的是启动 HTTP请求并立即显示其他内容(如微调器或“loading ...”消息)。然后,当HTTP请求完成时,使用新信息更新您的显示。

我在MSDN article on async MVVM data binding中有更多详细信息和示例代码。

答案 1 :(得分:1)

尝试将异步代码移出构造函数。一种常见的方法是覆盖OnAppearing()来执行工作。您可能还希望在UI中显示ActivityIndicator,直到加载数据:

public partial class ContactInfo : ContentPage
{
    private County item;

    public static async Task<string> GetContactString(string contactid)
    {
        HttpClient client = new HttpClient();
        var url = $"http://sema.dps.mo.gov/county/service.php?id={contactid}";
        var response = await client.GetAsync(url);
        if (response.IsSuccessStatusCode)
        {
            var responsetext = await response.Content.ReadAsStringAsync();
            return responsetext;
        }
        throw new Exception(response.ReasonPhrase);
    }

    public ContactInfo()
    {
        InitializeComponent();
        ContactInfoList = new ObservableCollection<ContactInfoModel>();
    }

    ObservableCollection<ContactInfoModel> ContactInfoList;

    public ContactInfo(County item) : this()
    {
        this.item = item;
        this.BindingContext = ContactInfoList;
    }

    protected override async void OnAppearing ()
    {
        if (item == null)
            return;
        var contact = await GetContactString(item.id);
        var models = JsonConvert.DeserializeObject<List<ContactInfoModel>>(contact);
        foreach (var model in models)
            ContactInfoList.Add(model);
    }
}

要解决绑定问题,请认识到您正在将列表本身分配给页面的BindingContext。你可以做以下两件事之一:

  1. 将ListView XAML中的ItemsSource="{Binding ContactInfoList}"更改为ItemsSource="{Binding .}"
  2. 将构造函数中的this.BindingContext = ContactInfoList;更改为this.BindingContext = this;
  3. 首选选项#1。