我正在使用Xamarin和C#来创建一些基本的Android应用程序。 我在学习过程中。
我要做的是使用JSON文件中的一些数据提取填充ListView。 我做了两个方法,一个用于调用服务器的异步任务,另一个用于解析和提取数据(http://mysafeinfo.com/api/data?list=englishmonarchs&format=json)。
我现在的问题是我不知道如何用这些数据提供listview。
感谢您的时间。
namespace App4
{
[Activity(Label = "App4", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
//Declare a Cancellation Token Source
CancellationTokenSource cts;
Button startbutton;
Button stopbutton;
TextView textView0;
ListView listView;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
startbutton = FindViewById<Button>
(Resource.Id.startbutton);
stopbutton = FindViewById<Button>
(Resource.Id.stopbutton);
textView0 = FindViewById<TextView>
(Resource.Id.textView0);
listView = FindViewById<ListView>
(Resource.Id.listView);
//BASIC ASYNC START TASK
// click the startbutton to start the process
startbutton.Click += async (sender, e) =>
{
// Instantiate the CancellationTokenSource
cts = new CancellationTokenSource();
try
{
// **** GET ****
await Task.Run(() => LoadDataAsync(cts.Token));
}
catch (TaskCanceledException)
{
textView0.Text = " Download deleted ";
}
catch (Exception)
{
textView0.Text = "Generic Error";
}
// ***Set the CancellationTokenSource to null when the download is complete.
cts = null;
};
//STOP BUTTON
stopbutton.Click += (sender, e) =>
{
if (cts != null)
{
cts.Cancel();
}
};
}
//THIS METHOD LOAD JSON DATA FROM AN URL AND RETURN A STRING
public static async Task<string> LoadDataAsync(CancellationToken ct)
{
// Call the server and take the file
var client = new HttpClient();
client.MaxResponseContentBufferSize = 1024 * 1024; //read up to 1MB of data
await Task.Delay(250);//Delay the task for deleting purpose
var response = await client.GetAsync(new Uri("http://mysafeinfo.com/api/data?list=englishmonarchs&format=json"), ct);
var result = await response.Content.ReadAsStringAsync();
return result;
}
//THIS METHOD GET THE JSON DATA FROM THE STRING
private static void GetData(string result)
{
// Parse the Json file.
JArray file = JArray.Parse(result);
foreach (var item in file.Children<JObject>())
{
string name = (string)item.SelectToken("nm");
string city = (string)item.SelectToken("cty");
string house = (string)item.SelectToken("hse");
string years = (string)item.SelectToken("yrs");
}
}
}
}
答案 0 :(得分:1)
您需要做一些事情,并建议您更改其他一些内容,以便更轻松。
首先使用您将从API接收的数据创建一个实体/类。按照您的意愿调用它,但对于此示例,我将其称为 EnglishMonarch
public class EnglishMonarch
{
public string Name {get; set;}
public string City {get; set;}
public string House {get; set;}
public string Years {get; set;}
}
如您所见,我为您将收到的每个字段添加了公共属性。
我建议你使用这个库Json.net,它允许你只用几行代码就可以将json数据解析成你的实体。您可以直接从XS或VS安装nuget包。
您需要在我们刚刚创建的类中包含一些更改。您将添加一些注释,以便json.net知道如何使用您的类属性映射每个json字段。
public class EnglishMonarch
{
[JsonProperty("nm")]
public string Name { get; set; }
[JsonProperty("cty")]
public string City { get; set; }
[JsonProperty("hse")]
public string House { get; set; }
[JsonProperty("yrs")]
public string Years { get; set; }
}
现在你可以得到响应并使用json.net解析它:
public List<EnglishMonarch> GetData (string jsonData)
{
if (string.IsNullOrWhiteSpace (jsonData))
return new List<EnglishMonarch> ();
return JsonConvert.DeserializeObject<List<EnglishMonarch>> (jsonData);
}
注意:为什么列出EnglishMonarch
?因为您从API接收了多个项目,这是您用来填充ListView
的列表。
现在让我们将这些数据放入ListView。在Android中,您需要创建一个Adapter,告诉ListView
如何以及要显示的数据。
您的适配器将如下所示:
public class EnglishMonarchAdapter : BaseAdapter<EnglishMonarch>
{
public List<EnglishMonarch> Items { get; set;}
private readonly Context context;
public EnglishMonarchAdapter (Context context, List<EnglishMonarch> items)
{
this.context = context;
Items = items ?? new List<EnglishMonarch> ();
}
public override EnglishMonarch this [int position]
{
get { return Items [position]; }
}
public override int Count
{
get { return Items.Count; }
}
public override long GetItemId (int position)
{
return position;
}
public override View GetView (int position, View convertView, ViewGroup parent)
{
var view = convertView ?? LayoutInflater.FromContext (context).Inflate (Resource.Layout.englishmonarch_item_layout, parent, false);
var item = Items [position];
var tvName = view.FindViewById<TextView> (Resource.Id.tvName);
var tvHouse = view.FindViewById<TextView> (Resource.Id.tvHouse);
var tvYear = view.FindViewById<TextView> (Resource.Id.tvYears);
var tvCity = view.FindViewById<TextView> (Resource.Id.tvCity);
tvName.Text = item.Name;
tvHouse.Text = item.House;
tvYear.Text = item.Years;
tvCity.Text = item.City;
return view;
}
}
GetView
方法负责创建ListView项目视图(Cell)并将数据映射到视图中的字段。
要使此适配器工作,您需要创建一个布局(XML),它将用作ListView的ItemView / Cell。我创建的那个非常简单,我把它命名为 englishmonarch_item_layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/tvName"
android:textSize="16sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/tvCity"
android:textSize="14sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/tvHouse"
android:textSize="11sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/tvYears"
android:textSize="11sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
现在您只需要粘贴startButton
点击事件
startbutton.Click += async (sender, e) =>
{
// Instantiate the CancellationTokenSource
cts = new CancellationTokenSource();
try
{
// **** GET ****
var jsonData = await LoadDataAsync(cts.Token);
// ** Parse data into your entity ****
var items = GetData(jsonData);
// **** Create your adapter passing the data *****
listview.Adapter = new EnglishMonarchAdapter(this, items);
}
catch (TaskCanceledException)
{
textView0.Text = " Download deleted ";
}
catch (Exception)
{
textView0.Text = "Generic Error";
}
// ***Set the CancellationTokenSource to null when the download is complete.
cts = null;
};
这就是全部。这应该有效!
注意:您可以跳过一些部分,例如使用Json.net并手动解析数据,只是提到它,以便您知道其他选项。