This app gets the device coordinates, what can take some seconds. Then it makes a request to an url that does some calcs and echoes a string where each property is separated by ',' and each item by '/'.
So I split the result and use foreach to loop by the items. As you can imagine, it takes a while and before things are ok the UI is completed but the data is not binding since it's not done yet, and it gets worst, because some times the app crashs throwing "Array index out of bounds" exception, it's because the foreach is reached without had received the result of the url request. I almost forget, at android emulator it works, I think it's because it runs really slowlly here, so the delay to url response doesn't matter too much but at a real device the UI is very fast so this problem happens.
I lost about 3 days with this, I'm loosing my hair, I really would apreciate if anybody could help me on this. God bless you.
Example of data that comes from url:
3,Name1,25/1,Name2,39/5,Name3,52/4,Name4,360
XAML File:
<ScrollView>
<StackLayout Orientation="Horizontal">
<ListView x:Name="ListViewLista" ItemsSource="{Binding .}" ItemTapped="ListViewLista_ItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Height="30">
<ViewCell.View>
<StackLayout BackgroundColor="#eee" Orientation="Vertical" HeightRequest="30">
<StackLayout Orientation="Horizontal" HeightRequest="30" Padding="0,6,0,0">
<Image Source="example_com/img.png" HeightRequest="30" WidthRequest="30" Margin="5,0,5,0" VerticalOptions="Center" />
<Label Text="{Binding Nick}" HorizontalOptions="StartAndExpand" TextColor="Black" VerticalOptions="Center" />
<Label Text="{Binding Distancia}" HorizontalOptions="EndAndExpand" TextColor="Black" Margin="0,0,8,0" VerticalOptions="Center" />
</StackLayout>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ScrollView>
Code Behind .cs:
public partial class Listar : ContentPage
{
public Listar ()
{
InitializeComponent();
}
protected override async void OnAppearing()
{
string resultRequest= await GetOnlineUsers();
Usuarios ListaUsers = new Usuarios();
BindingContext = await ListaUsers.GetDefaults(resultRequest.Split('/'));
}
public class Usuarios
{
public async Task<List<Usuario>> GetDefaults(string[] UsuariosArgList)
{
List<Usuario> lista = new List<Usuario>();
int i = 0;
foreach(string each in UsuariosArgList)
{
string[] DataInfo = each.Split(',');
lista.Add(new Usuario(){
Index = i,
DatabaseDeviceId = int.Parse(DataInfo[0]),
Nick = DataInfo[1],
Distancia = DataInfo[2]
});
i++;
//for debug purpose Console.WriteLine(each);
}
return lista;
}
}
public class Usuario
{
public int Index { get; set; }
public int DatabaseDeviceId { get; set; }
public string Nick { get; set; }
public string Distancia { get; set; }
}
private async Task<string> GetOnlineUsers()
{
try
{
using (WebClient browser = new WebClient())
{
string resultado = await browser.DownloadStringTaskAsync("example_com/getUsers.php?lat=" + GetLatitude() + "&lon=" + GetLongitude() + "&raiokm=20000.0");
return resultado;
}
}
catch (Exception)
{
throw;
}
}