【问题标题】:Xamarin android fill listview async with progressbarXamarin android用进度条填充listview异步
【发布时间】:2016-12-07 14:49:52
【问题描述】:

如何在 Xamarin.Android 中在 Activity 的 onCreate 上填充 ListView async? 我知道如何在单击按钮时调用异步方法并添加进度条,但是如何对 onCreate 方法执行相同操作? 我需要的是在加载 20.000 个项目的列表时打开活动并显示进度条。

在 Eclipse Java 中,我曾经调用 AsyncTask (onpreexecute ... doinbackgroud ...onpostexecute),但在 Xamarin 中我不知道如何执行此操作。 有这方面的帮助或教程吗?

我使用@Yuri 提供的方法尝试了这种方式,但仍然无法正常工作:

 async protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.PulledItemsList);
        ActionBar.SetDisplayHomeAsUpEnabled(true);
        ActionBar.Title = "Catalog";
        _activity = this;

        //display your activity indicator and start spin
        ProgressDialog progressdialog = new ProgressDialog(this);
        progressdialog.SetCancelable(false);
        progressdialog.Indeterminate = true;
        progressdialog.SetMessage("Loading...");
        progressdialog.SetProgressStyle(ProgressDialogStyle.Spinner);
        progressdialog.Show();
        await Task.Run(() =>
        {
            fillListView();
        })
           .ContinueWith((t) =>
         {
             RunOnUiThread(() =>
                        {
                            progressdialog.Hide();
                            progressdialog.Dismiss();
                        });
         });
 }

还有这个方法:

 async protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.PulledItemsList);
        ActionBar.SetDisplayHomeAsUpEnabled(true);
        ActionBar.Title = "Catalog";
        _activity = this;
        //display your activity indicator and start spin
        ProgressDialog progressdialog = new ProgressDialog(this);
        progressdialog.SetCancelable(false);
        progressdialog.Indeterminate = true;
        progressdialog.SetMessage("Loading...");
        progressdialog.SetProgressStyle(ProgressDialogStyle.Spinner);
        progressdialog.Show();

        await Task.Run(() =>
        {
            RunOnUiThread(() =>
            {
              fillListView();
            });
        });

         progressdialog.Hide();
         progressdialog.Dismiss();

        //disable indicator, list loaded
    }

而fillListView()函数是:

 private void fillListView()
    {
        var listview = FindViewById<ListView>(Resource.Id.listview);
        List<oneimg_twolbl> ItemObjectList = new List<oneimg_twolbl>();
        oneimg_twolbl ItemObject = new oneimg_twolbl(0, "", "");
        List<Items> Itemlist = Items.SelectFromItems();
        if (Itemlist.Count == 0)
        {
            Toast.MakeText(this, GetString(Resource.String.NoItems), ToastLength.Long);
        }
        foreach (Items current_item in Itemlist)
        {
            ItemObject = new oneimg_twolbl(Resource.Drawable.StockQty, current_item.ItemBarcode.ToString().Trim(), current_item.DisplayField.ToString().Trim(), current_item.ItemNum);
            ItemObjectList.Add(ItemObject);
        }
        adapter = new PulledItemList_Adapter(this, ItemObjectList);
        listview.Adapter = adapter;


        listview.ItemClick += delegate (object sender, AdapterView.ItemClickEventArgs args)
        {
            Intent i = new Intent(this, typeof(ManageItemsActivity));
            oneimg_twolbl clicked_Item = adapter.GetItem_bypos(args.Position);
            Items selected_Item = Items.SelectWhereFromItems(clicked_Item.Id);
            i.PutExtra("parameter1", ManageItemsActivity.EDITMODE);
            i.PutExtra("parameter2", selected_Item.ItemCode);
            i.PutExtra("parameter3", selected_Item.ItemNum);
            i.PutExtra("Displayfield", selected_Item.DisplayField);
            StartActivity(i);
        };
    }

适配器类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;

namespace SocrateMobile.Droid.Adapter
{
class PulledItemList_Adapter : BaseAdapter<oneimg_twolbl>
{
    private Activity context;
    private List<oneimg_twolbl> AllItemList;


    public PulledItemList_Adapter(Activity context, List<oneimg_twolbl> AllItemList)
    {
        this.AllItemList = AllItemList;
        this.context = context;
    }
    public oneimg_twolbl GetItem_bypos(int position)
    {
        return AllItemList[position];
    }
    public override oneimg_twolbl this[int position]
    {
        get { return AllItemList[position]; }
    }

    public override int Count
    {
        get { return AllItemList.Count; }
    }

    public override long GetItemId(int position)
    {
        return position;
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        Holder_oneimg_twolbl holder = null;
        var view = convertView;

        if (view != null)
            holder = view.Tag as Holder_oneimg_twolbl;


        if (holder == null)
        {
            holder = new Holder_oneimg_twolbl();
            view = context.LayoutInflater.Inflate(Resource.Layout.oneimg_twolbl, null);
            holder.Text = view.FindViewById<TextView>(Resource.Id.text_list4_view);
            holder.Text2 = view.FindViewById<TextView>(Resource.Id.text_list4_view2);
            holder.Image = view.FindViewById<ImageView>(Resource.Id.image_list4_view);
            view.Tag = holder;
        }

        var current_item = AllItemList[position];


        holder.Text.Text = current_item.FirstTxt;
        holder.Text2.Text = current_item.SecondTxt;
        holder.Image.SetImageResource(current_item.FirstImg);
        holder.holderId = current_item.Id;

        if (!holder.Image.HasOnClickListeners)
        {
            holder.Image.Click += delegate
            {
                PulledItemListActivity Itemlistactivity = new                PulledItemListActivity();
                Itemlistactivity.QtyImageClick(holder.holderId);
            };
        }

        return view;
    }



    public class Holder_oneimg_twolbl : Java.Lang.Object
    {
        public TextView Text { get; set; }
        public TextView Text2 { get; set; }
        public ImageView Image { get; set; }

        public int holderId { get; set; }
    }
}
}

【问题讨论】:

    标签: android listview xamarin android-asynctask xamarin.android


    【解决方案1】:

    根据您的代码,这里是如何做您需要的:

    在 OnCreate 调用中

            await Task.Run(() =>
            {
                fillListView();
            });
    

    您填写的listview 函数将如下所示。我不得不注释掉您的一些代码并添加延迟进行测试。您可以恢复您的代码,但请记住,您需要在将对象放入之前设置适配器。然后它将在微调器工作时更新您的屏幕。如果您不需要,则不必调用 NotifyDataSetChanges。

    private void fillListView()
            {
                var listview = FindViewById<ListView>(Resource.Id.listView1);
                List<oneimg_twolbl> ItemObjectList = new List<oneimg_twolbl>();
    
    
    
                //oneimg_twolbl ItemObject = new oneimg_twolbl(0, "", "");
    
                //List<Items> Itemlist = Items.SelectFromItems();
                //if (Itemlist.Count == 0)
                //{
                //    Toast.MakeText(this, "No items", ToastLength.Long);
                //}
                //foreach (Items current_item in Itemlist)
                //{
                //    ItemObject = new oneimg_twolbl(Resource.Drawable.Icon, current_item.ItemBarcode.ToString().Trim(), current_item.DisplayField.ToString().Trim(), current_item.ItemNum);
                //    ItemObjectList.Add(ItemObject);
                //}
    
                var adapter = new PulledItemList_Adapter(this, ItemObjectList);
                listview.Adapter = adapter;
                for (int i = 0; i < 10; i++)
                {
                    RunOnUiThread(() =>
                    {
                        ItemObjectList.Add(new oneimg_twolbl(i, i.ToString(), i.ToString()));
                        adapter.NotifyDataSetChanged();
                    }); 
                    Task.Delay(500).Wait();
                }
    
    
    
                listview.ItemClick += delegate (object sender, AdapterView.ItemClickEventArgs args)
                {
                    //Intent i = new Intent(this, typeof(ManageItemsActivity));
                    //oneimg_twolbl clicked_Item = adapter.GetItem_bypos(args.Position);
                    //Items selected_Item = Items.SelectWhereFromItems(clicked_Item.Id);
                    //i.PutExtra("parameter1", ManageItemsActivity.EDITMODE);
                    //i.PutExtra("parameter2", selected_Item.ItemCode);
                    //i.PutExtra("parameter3", selected_Item.ItemNum);
                    //i.PutExtra("Displayfield", selected_Item.DisplayField);
                    //StartActivity(i);
                };
            }
    

    【讨论】:

    • 我试过你的方法。当我尝试填写列表时,第一个给了我一个例外:Android.Util.AndroidRuntimeException: 只有创建视图层次结构的原始线程才能触及它的视图。第二个我有 RunOnUiThread我在 task.run 中填写了列表并在 RunOnUiThread 中取消了进度,它接缝它可以工作,但我看不到任何行(列表未填写),当我单击返回或打开一个新活动时,我得到一个异常: Java.Lang.IllegalArgumentException:观察者为空。
    • 对于第一种方法,您还应该在填充列表的代码周围使用 RunOnUiThread(()=>。sedcond 应该给您同样的异常,因为它也不受 RunOnUiThread 保护所以我假设您将您的列表填充代码放在 ContinueWith 中,这是错误的,它应该在 Task.Run 中,并且只有 Dismiss 应该在 ContinueWith 中。我更新了我的答案。关于空观察者或其他东西 - 这与我提供的代码无关。检查你的填充绑定代码
    • 如果您提供示例解决方案,我可能会提供更多帮助
    • 这方面有什么进展吗?
    • 你好@Yuri 抱歉迟到了。当我将 RunOnUiThread 添加到第一个方法时它显示它没有工作......它在加载列表之前显示黑屏。第二种方法我显示了进度,但我仍然看不到列表。我将更新我的问题并添加两个代码案例
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多