Reputation: 2738
I have a weird / unique situation with my ListView
. This is the scenario:
I'm making use of the MVP design pattern. As the Activity
starts, it raises an event to notify the presenter to fetch some data from a web service. The web service call is an Async call. Once the web service Completed
event is raised, I take the result and push it into a property (which is of type Array) that resides within my View
/ Activity
.
Everything I mentioned works just fine, but as soon as the device is rotated, some interesting developments take place.
The async call resumes as normal and provides the property (Array) with a value. So nothing wrong there... (And yes there is data in the collection) I then set the ListView Adapter
and call the notifyDataSetChanged
, but nothing happens. The UI is not updated or anything?? If I re-enter the Activity
the data is visible again ??
I even tried calling invalidateViews
and invalidate
on the ListView
- this didn't do anything.
Could someone please assist me in this matter? Many thanks in advance!
[Update]
I would like to stress the fact that I am making use of C# (Xamarin) and not Java (:sigh: - yes I know). Furthermore, I am not making use of the ASyncTask
class, instead I'm making use of the async methods created within the proxy classes generated by Visual Studio. Pretty straight forward, but this is the code that populates the ListView
- the property is set from the presenter
Presenter
Where View is of type IContactsView
protected override void OnCollectData(System.Collections.IEnumerable data, Type typeOfData)
{
if (data != null && typeOfData != null && typeOfData.Equals(typeof(UserContact)))
{
this.View.UserInformationCollection = data.Cast<UserContact>().ToArray();
}
}
Activity
The activity implements IContactsView
public UserContact[] UserInformationCollection
{
get
{
return this._userInformationCollection;
}
set
{
this.RunOnUiThread(() =>
{
this._userInformationCollection = value;
ListView listview = this.FindViewById<ListView>(Resource.Id.userLV);
if (listview != null)
{
UserContact[] subsidiesList = this.GetIndexedContacts(this._userInformationCollection);
listview.Adapter = new ContactsAdapter(this, subsidiesList.ToList());
((ContactsAdapter)listview.Adapter).NotifyDataSetChanged();
}
});
}
}
[/Update]
Upvotes: 1
Views: 636
Reputation: 2738
Found a much better solution! So please ignore the static variable
idea!
Activity:
Override the OnRetainNonConfigurationInstance
and return the presenter
public override Java.Lang.Object OnRetainNonConfigurationInstance()
{
return this._presenter;
}
Within the OnCreate
check the LastNonConfigurationInstance
and get the presenter - if it isn't null:
protected override void OnCreate(Bundle bundle)
{
...
if (this.LastNonConfigurationInstance != null)
{
this._presenter = this.LastNonConfigurationInstance as ContactsPresenter;
this._presenter.RefreshView(this);
}
else
{
// create a new presenter
this._presenter = new ContactsPresenter(this);
}
...
}
So maybe, you saw what I did in the previous code sample? Yes, I send the new instance of the activity to the presenter - have a look at the RefreshView
Presenter:
So within my base presenter I have the following method:
public class Presenter<T> : Java.Lang.Object, IPresenter where T : IView
{
/// <param name="view">The view.</param>
public void RefreshView(T view)
{
this.View = view;
}
}
The above code helps my presenter say with the creation of new activities - so when it returns data after the async call it will have the latest and greatest instance of the activity!
Hope this helps! Kind regards,
Upvotes: 2
Reputation: 2738
Got it working by doing the following:
declare a static variable of the activity:
private static ContactsActivity _cachedActivity = null;
Overrode the OnResume
within the activity and set the variable:
protected override void OnResume()
{
base.OnResume();
_cachedActivity = this;
}
Override the OnCreate
within the activity and set the variable:
protected override void OnCreate(Bundle bundle)
{
...
_cachedActivity = this;
...
}
Lastly I changed the property mentioned earlier:
public USBUserContact[] UserInformationCollection
{
get
{
return this._userInformationCollection;
}
set
{
_cachedActivity.RunOnUiThread(() =>
{
_cachedActivity._userInformationCollection = value;
ListView listview = _cachedActivity.FindViewById<ListView>(Resource.Id.userLV);
if (listview != null)
{
UserContact[] subsidiesList = _cachedActivity.GetIndexedContacts(_cachedActivity._userInformationCollection);
listview.Adapter = new ContactsAdapter(_cachedActivity, subsidiesList.ToList());
((ContactsAdapter)listview.Adapter).NotifyDataSetChanged();
}
});
}
}
Kind regards,
Upvotes: 1