在Fragment中更新ListView - Xamarin.Android

时间:2016-02-22 17:31:58

标签: android listview android-fragments xamarin

我是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.

任何想法如何解决?

2 个答案:

答案 0 :(得分:0)

好吧,我删除了OnResumeUpdateView方法重写我的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();
            });
        }
    });
}

所以,基本上,我在OnCreateOnCreateView方法中复制了代码。奇怪的。 =)

答案 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线程。所以不应该为此做任何特殊的考虑。