2

In a Xamarin project, Android - I am new to android development. While working on a activity, in the OnCreate method am setting a custom Adapter for a ListView.

protected async override void OnCreate (Bundle bundle)
{
    base.OnCreate (bundle);
    SetContentView(Resource.Layout.Main);

    var listAdapter = new CustomListAdapter(this);
    //.................................................
    listView = (ListView) FindViewById(Resource.Id.list);

    // populate the listview with data
    listView.Adapter = listAdapter;
}

In the ctor of the adapter, creating a list of items in async call.

public CustomListAdapter(Activity context) //We need a context to inflate our row view from
    : base()
{
    this.context = context;
    // items is List<Product>
    items = await GetProductList();
}

Since Getproducts is a async call, it will load the data asynchronously.

The problem is once i set the adapter to the list it will try invoke the GetView method of adapter. At that time, items will not be loaded. so there is a null exception.

How to handle this situation.

Thanks.

i3arnon
  • 113,022
  • 33
  • 324
  • 344
Sankarann
  • 2,625
  • 4
  • 22
  • 59
  • I've never used xamarin so I don't know if this applies but it should http://stackoverflow.com/questions/19039868/androidsimpleadapter-error/19040185#19040185 – codeMagic May 26 '15 at 13:58

2 Answers2

5

You can't use await in a constructor.

There are several things you can do instead. The best here IMO is to have a separate async method that you call and await after you create the object.

var listAdapter = new CustomListAdapter(this);
await listAdapter.InitializeAsync();

Another option is to make the constructor private and have an async static method that creates the instance and initializes it:

public static async Task<CustomListAdapter> CustomListAdapter.CreateAsync(Activity context)
{
    var listAdapter = new CustomListAdapter(context);
    listAdapter.items = await GetProductList();
    return listAdapter;
}
i3arnon
  • 113,022
  • 33
  • 324
  • 344
  • 1
    You beat me to the answer! :D So I'm upvoting yours. – Rajshri Mohan K S May 26 '15 at 14:03
  • 1
    furthermore, an adapter constructor may not be the best place to load stuff. I would fill the adapter from the OnCreate() listAdapter.AddAll(await GetProductList()); – Benoit Jadinon May 26 '15 at 20:44
  • I couldn't see the InitializeAsync method in my Adapter. From which base this method is implemented? – Sankarann May 27 '15 at 06:37
  • 1
    @Sankarann It's not an existing method. The idea is that you take out what you want to do in the constructor into an async method so you can call it and await the returned task. – i3arnon May 27 '15 at 06:56
-1

Maybe override the getCount so if items is still null or items has zero items return that the listView size should be 0.

public int getCount() {
    return items != null ? items.size() : 0;
}
Aegis
  • 5,761
  • 2
  • 33
  • 42