我是Android开发人员的新手,所以对我来说这段代码有什么问题真的很奇怪。
我在xamarin论坛上花了很多时间,最后我放弃了,所以请你帮忙。
namespace App1.Fragments
{
public class HomePage : Android.Support.V4.App.Fragment
{
private List<Model.Photo> photos;
private ListView listview;
private MyListViewAdapter adapter;
private bool IsLoading = false;
private int Treshhold = 10;
private int PreviousTotalItemCount = 0;
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
}
public override void OnResume()
{
base.OnResume();
try
{
var task = Task.Run(async delegate
{
photos = await API.GetLatestPhotos();
}).ContinueWith(delegate
{
using(var h = new Handler(Looper.MainLooper))
{
h.Post(delegate
{
UpdateView(); // I cannot call this.RunOnUIThread(delegate{ //code });
});
}
});
task.Wait();
}
catch { }
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
photos = new List<Model.Photo>();
View view = inflater.Inflate(Resource.Layout.HomePage, container, false);
listview = view.FindViewById<ListView>(Resource.Id.List);
adapter = new MyListViewAdapter(this, photos);
listview.Adapter = adapter;
listview.ScrollStateChanged += Listview_ScrollStateChanged;
UpdateView();
return view;
}
private void UpdateView()
{
if(adapter != null)
adapter.NotifyDataSetChanged();
}
private async void Listview_ScrollStateChanged(object sender, AbsListView.ScrollStateChangedEventArgs e)
{
int last = listview.LastVisiblePosition;
int total = listview.Adapter.Count;
if(IsLoading && total > PreviousTotalItemCount)
{
IsLoading = false;
PreviousTotalItemCount = total;
}
if((last + Treshhold) >= total && !IsLoading)
{
IsLoading = true;
var items = await API.GetLatestPhotos(API.LastPhotoID);
foreach(var item in items)
photos.Add(item);
adapter.NotifyDataSetChanged();
}
}
}
public class MyListViewAdapter : BaseAdapter<Model.Photo>
{
List<Model.Photo> items;
Activity context;
public MyListViewAdapter(Android.Support.V4.App.Fragment context, List<Model.Photo> items) : base()
{
this.context = context.Activity;
this.items = items;
}
public override long GetItemId(int position)
{
return position;
}
public override Model.Photo this[int position]
{
get { return items[position]; }
}
public override int Count
{
get { return items.Count; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = items[position];
View view = convertView;
if(view == null) // no view to re-use, create new
view = context.LayoutInflater.Inflate(Resource.Layout.MyListView, null);
Koush.UrlImageViewHelper.SetUrlDrawable(view.FindViewById<ImageView>(Resource.Id.Image), item.StoragePath);
return view;
}
}
}
所有数据上传,没关系,但我的列表视图不会更新。
如果我试图在UI线程中调用adapter.NotifySetDataChanged()
,我已经Skippen *n* frames. Too much work in current thread.
任何想法如何解决?
答案 0 :(得分:0)
好吧,我删除了OnResume
和UpdateView
方法重写我的OnCreate
方法,如下所示:
public override async void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
await Task.Run(async delegate
{
photos = await API.GetLatestPhotos();
using(var h = new Handler(Looper.MainLooper))
{
h.Post(delegate
{
listview = this.Activity.FindViewById<ListView>(Resource.Id.List);
adapter = new MyListViewAdapter(this, photos);
listview.Adapter = adapter;
adapter.NotifyDataSetChanged();
});
}
});
}
所以,基本上,我在OnCreate
和OnCreateView
方法中复制了代码。奇怪的。 =)
答案 1 :(得分:0)
这应该可以正常工作......
public override async void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
//maybe show some kind of wait spinner?
photos = await API.GetLatestPhotos();
listview = this.Activity.FindViewById<ListView>(Resource.Id.List);
adapter = new MyListViewAdapter(this, photos);
listview.Adapter = adapter;
}
当您分配Adapter
时,您也不需要拨打NotifyDataSetChanged
。设置适配器后,将刷新数据集。
此外,由于代码从UI线程开始(OnCreate
在UI线程上运行),await
调用将返回UI线程。所以不应该为此做任何特殊的考虑。