2017-03-20 1 views
0

Ich benötige ein anderes Content zu starten, bevor diese Asynchron-Methode Wert zurückgibt:Navigieren Sie zu einem anderen Content von Asynchron-Verfahren vor dem Asynchron-Methode gibt einen Wert

public class GettingCountry : ContentPage 
{ 
    public static List<string> CountriesList = new List<string>(); 

    MainPage mainPage = new MainPage(); 
    public async Task<List<RootObject>> FetchAsync(string url) 
    { 
     string jsonString; 
     using (var httpClient = new System.Net.Http.HttpClient()) 
     { 
      var stream = await httpClient.GetStreamAsync(url); 
      StreamReader reader = new StreamReader(stream); 
      jsonString = reader.ReadToEnd(); 
     } 

     var listOfCountries = new List<RootObject>(); 

     var responseCountries = JArray.Parse(JObject.Parse(jsonString)["response"]["items"].ToString()); 

     foreach (var countryInResponse in responseCountries) 
     { 
      var rootObject = new RootObject((int)countryInResponse["id"], (string)countryInResponse["title"]); 

      CountriesList.Add(rootObject.Title); 
     } 

     //I NEED TO NAVIGATE TO FillingPage() FROM HERE: 
     await Navigation.PushAsync(new FillingPage()); 

     //await Navigation.PushModalAsync(new NavigationPage(new FillingPage())); 

     return listOfCountries; 
    } 

Die Seite, die werden müssen gestartet ist:

[XamlCompilation(XamlCompilationOptions.Compile)] 
public partial class FillingPage : ContentPage 
{ 
    public FillingPage() 
    { 
     GettingCountry gettingCountry = new GettingCountry(); 

     Label header = new Label 
     { 
      Text = "Заполните бланк", 
      FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)), 
      HorizontalOptions = LayoutOptions.Center, 
      VerticalOptions = LayoutOptions.CenterAndExpand, 
      TextColor = Color.Blue 
     }; 

     Entry nameEntry = new Entry() 
     { 
      Placeholder = "Имя", 
     }; 

     Entry surnameEntry = new Entry() 
     { 
      Placeholder = "Фамилия" 
     }; 

     Picker countryPicker = new Picker() 
     { 
      Title = "Страна", 
      VerticalOptions = LayoutOptions.CenterAndExpand 
     }; 

     foreach (string country in GettingCountry.CountriesList) 
     { 
      countryPicker.Items.Add(country); 
     } 

     SearchBar townSearchBar = new SearchBar() 
     { 
      Placeholder = "Город", 
      SearchCommand = new Command(() => 
      { 
      }) 
     }; 

     SearchBar universitySearchBar = new SearchBar() 
     { 
      Placeholder = "Университет", 
      SearchCommand = new Command(() => 
      { 
      }) 
     }; 
     Button myButton = new Button() 
     { 
      TextColor = Color.Green, 
      Text = "Выполнить", 
      FontSize = 22 
     }; 

     // Accomodate iPhone status bar. 
     this.Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5); 

     // Build the page. 
     this.Content = new StackLayout 
     { 
      Children = 
      { 
       header, 
       nameEntry, 
       surnameEntry, 
       countryPicker, 
       townSearchBar, 
       universitySearchBar, 
       myButton 
      } 
     }; 
    } 
} 

}

Aber dieser Code await Navigation.PushAsync(new FillingPage()); gut funktioniert nur, wenn ich eine Taste drücken. Wenn ich einen Knopf drücke, startet die benötigte Seite gut. Aber derselbe Code in einer Methode funktioniert nicht. Ich habe es ausgetragen. Es geht auf eine FillingPage(), aber startet es nicht, wenn ich versuche, es aus der asynchronen Methode zu starten.

+0

Nur ein paar für Kommentare, völlig unabhängig zu Ihrer Frage. Sie können 'httpClient.GetStringAsync()' verwenden, um die Zeichenfolge direkt abzurufen. Und es ist leistungsfähiger, den 'HttpClient' nicht zu entfernen. Im Hintergrund ist es eine gemeinsam genutzte Instanz zwischen allen Anfragen, und wenn Sie es entsorgen, entsteht mehr Overhead. Sehen Sie hier für Details: https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/ –

Antwort

3

Dies ist wahrscheinlich ein Ergebnis der Operation, die nicht im Hauptthread ausgeführt wird. Versuchen Sie wickeln Sie den Code wie folgt aus:

Device.BeginInvokeOnMainThread(async() => 
{ 
    await Navigation.PushAsync(new FillingPage()); 
} 

Edit: Nach einer privaten Nachricht, erfuhr ich, dass es nicht genügend Informationen in der Frage war das eigentliche Problem zu kennen. Die Anwendung ruft FetchAsync in Application.OnStart und es ist nicht Teil der Ansicht Hierarchie überhaupt nicht so Navigationsmethoden würde nicht funktionieren. Folgendes wurde zur Verfügung gestellt:

protected override void OnStart() 
{ 
    getCountry(); 
} 

private async void getCountry() 
{ 
    var url = "..."; 
    GettingCountry gettingCountry = new GettingCountry(); 
    await gettingCountry.FetchAsync(url); 
} 

GettingCountry ist ein ContentPage wie eine Art von Datenzugriffsklasse verwendet wird, und es ist derzeit nicht Teil der UI als MainPage auf etwas anderes festgelegt ist. Eine schnelle Hack wäre etwas mehr wie:

private async void getCountry() 
{ 
    var url = "..."; 
    GettingCountry gettingCountry = new GettingCountry(); 
    var data = await gettingCountry.FetchAsync(url); 
    await MainPage.Navigation.PushAsync(new FillingPage(data)); 
} 

Ich würde zwei weitere Bereiche zu verbessern aussehen vorschlagen. Betrachten

  1. Refactoring GettingCountry, da es kein ContentPage sein muss.
  2. Untersuchen Sie einen alternativen Anruf, sodass async void nicht verwendet wird.
+2

Warum der Downvote? Was könnte ich tun, um die Antwort zu verbessern? – therealjohn

+0

Device.BeginInvokeOnMainThread war die Antwort, die ich brauchte. Ich habe versucht, die MainPage in einem asynchronen Thread zu ändern. Ich hätte es auf der UI/Main Thread tun sollen. Eine Lektion, die ich nicht so schnell vergessen werde. –

Verwandte Themen