2017-05-18 4 views
0

Ich arbeite mit Xamarin und C#, um einige grundlegende Android-Anwendung zu erstellen. Ich bin im Lernprozess.Füllen Sie eine ListView aus einer JSON-Datei in C#

Was ich versuche zu tun, ist ein ListView mit einigen Datenextrakt aus einer JSON-Datei zu füllen. Ich habe zwei Methoden erstellt, eine asynchrone Aufgabe zum Aufrufen des Servers und eine zum Analysieren und Extrahieren der Daten (http://mysafeinfo.com/api/data?list=englishmonarchs&format=json).

Mein Problem ist jetzt, dass ich keine Ahnung habe, wie man den Listview mit diesen Daten füttert.

Vielen Dank für Ihre Zeit.

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

müssen Sie ein Domänenobjekt mit Eigenschaften für jedes Datenelement (Name, Stadt usw.) erstellen und dann eine Liste dieser Objekte in Ihrer GetData-Methode erstellen. Sie verwenden einen ListAdapater, um diese Daten an Ihren ListView zu senden. – Jason

Antwort

1

Sie müssen ein paar Dinge und wird vorschlagen, dass Sie ein paar andere ändern, so dass es leichter sein kann.

Erstellen Sie zuerst eine Entität/Klasse mit den Daten, die Sie von der API erhalten. Nennen Sie es, wie Sie, aber für dieses Beispiel wollen werde ich nenne es EnglishMonarch

public class EnglishMonarch 
{ 
    public string Name {get; set;} 

    public string City {get; set;} 

    public string House {get; set;} 

    public string Years {get; set;} 
} 

Wie Sie sehe ich eine öffentliche Eigenschaft mit jedem Feld hinzugefügt Sie empfangen werden.

Ich empfehle Ihnen, diese Bibliothek Json.net verwenden, mit denen Sie die JSON-Daten mit nur ein paar Zeilen Code in Ihre Entität analysieren können. Sie können das Nuget-Paket direkt von XS oder VS installieren.

Sie müssen einige Änderungen an der Klasse vornehmen, die wir gerade erstellt haben. Sie werden einige Anmerkungen hinzufügen, damit json.net weiß, wie Sie jedes json-Feld mit Ihren Klasseneigenschaften abbilden können.

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; } 
} 

Jetzt können Sie die Antwort erhalten und analysieren mit es json.net wie folgt aus:

public List<EnglishMonarch> GetData (string jsonData) 
{ 
    if (string.IsNullOrWhiteSpace (jsonData)) 
     return new List<EnglishMonarch>(); 

    return JsonConvert.DeserializeObject<List<EnglishMonarch>> (jsonData); 
} 

Hinweis: Warum eine Liste von EnglishMonarch? Da Sie von der API mehr als ein Element erhalten, ist dies die Liste, die Sie verwenden werden, um Ihre ListView zu füllen.

Jetzt fügen wir diese Daten in Ihr ListView ein. In Android für diese müssen Sie eine Adapter erstellen, die die ListView wie und welche Daten angezeigt wird.

Der Adapter wird wie folgt aussehen:

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; 
    } 
} 

Die GetView Methode derjenige der Schaffung der Listview-Artikel Ansicht verantwortlich ist (die Zelle) und Abbilden der Daten auf die Felder in der Ansicht.

Damit dieser Adapter funktioniert, müssen Sie ein Layout (XML) erstellen, das als ItemView/Cell Ihrer ListView verwendet wird.Die eine habe ich sehr einfach und ich nannte es 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> 

Jetzt müssen Sie nur noch ein paar Stücke in Ihrem startButton Click-Ereignis kleben

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; 
    }; 

Das ist alles. Das sollte funktionieren!

Hinweis: Sie können ein paar Teile wie die Verwendung von Json.net überspringen und Ihre Daten manuell analysieren, nur erwähnt, damit Sie wissen, dass es andere Optionen gibt.

+0

Dies ist eine vollständige und außergewöhnliche Antwort. Vielen Dank für Ihre Zeit! –

+0

markieren Sie seine Antwort als die richtige @AngelaAmeruoso – CDrosos

Verwandte Themen