Обновить пользовательский listviewAdapter

Я хочу добавить новые данные в свой listviewAdapter, я попробовал это, очистив все данные перед ним и уведомив, что теперь есть данные, но, похоже, это не работает. Я следовал решению (stackoverflow), но это не работает.

Кто-нибудь знает, почему?

public class ReportsListViewAdapter : BaseAdapter<IMobileReport>, IFilterable
{
    internal List<IMobileReport> originalData;
    internal List<IMobileReport> reports;
    private Context context;
    public override IMobileReport this[int position] => reports[position];

    public ReportsListViewAdapter(Context context, IEnumerable<IMobileReport> reports)
    {
        this.reports = reports.OrderBy(report => report.StudyDate).ToList();
        this.context = context;
        Filter = new ReportsFilter(this);
    }

    public override int Count => this.reports.Count;
    public Filter Filter { get; private set; }
    public override long GetItemId(int position)
    {
        return position;
    }

    public void updateReportsList(List<MobileReport> newlist)
    {
        reports.AddRange(newlist);
        this.NotifyDataSetChanged();
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        View row = convertView;
        if(row == null)
        {
            row = LayoutInflater.From(context).Inflate(Resource.Layout.listView_reports_row, null, false);
        }

        var txtName = row.FindViewById<TextView>(Resource.Id.txtName);
        txtName.Text = reports[position].Student.Name;

        var txtFirstName = row.FindViewById<TextView>(Resource.Id.txtFirstName);
        txtFirstName.Text = reports[position].Student.FirstName;

        var txtSource = row.FindViewById<TextView>(Resource.Id.txtSource);
        txtSource.Text = reports[position].Source;
        var txtCritical = row.FindViewById<TextView>(Resource.Id.txtCritical);
        txtSource.Text = reports[position].Critical.ToString();
        return row;

    }
}


protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        reports = new List<IMobileReport>();
        //Init();
        _reportsHubConnector = new ReportsHubConnector();

        #pragma warning disable 4014 // We cannot await this task here because the signature of the inherited method is void
        Task.Factory.StartNew(async () =>
        {
            await _reportsHubConnector.StartConnection();
            await _reportsHubConnector.SendT();

        }, TaskCreationOptions.PreferFairness);
        #pragma warning restore 4014

        Console.WriteLine("HomeActivity: OnCreate");
        SetContentView(Resource.Layout.activity_reports);
        SupportActionBar.SetDisplayShowTitleEnabled(false);
        SupportActionBar.SetDisplayHomeAsUpEnabled(false);
        SupportActionBar.SetDisplayShowHomeEnabled(true);

        WireUpElements();

        listView = FindViewById<ListView>(Resource.Id.reports);
        ReportsListViewAdapter adapter = new ReportsListViewAdapter(this, reports);

        listView.Adapter = adapter;

        searchView = FindViewById<SearchView>(Resource.Id.searchView1);
        searchView.QueryTextChange += this.Filter;

        listView.ItemClick += ItemClicked;

        criticalButton = FindViewById<LinearLayout>(Resource.Id.AuthenticatorButton);
        criticalButton.Click += criticalClicked;

        _reportsHubConnector.ReportsRecieved += (reports) =>
        {
            adapter.updateReportsList(reports);

        };
    }

Когда я медленно отлаживаю, GetView действительно срабатывает, возможно, это ключ к тому, почему он не вызывается, когда я не отлаживаю или не просматриваю код быстро.

This.RunOnUiThread никогда не вызывается, но вызывается update.

 _reportsHubConnector.ReportsRecieved += (tmpReports) =>
 {
       adapter.updateReportsList(tmpReports);
       this.RunOnUiThread(() =>
       {

            criticalButton.SetBackgroundColor(Android.Graphics.Color.Red);
        });
  };

person Max    schedule 29.04.2020    source источник


Ответы (1)


Я попробовал это с очисткой всех данных перед этим и уведомлением о том, что теперь есть данные, но, похоже, это не работает.

Из общего кода, не видя ясного метода, можно добавить reports.Clear(), чтобы проверить, работает ли он.

public void updateReportsList(List<MobileReport> newlist)
{
    reports.Clear();
    reports.AddRange(newlist);
    this.NotifyDataSetChanged();
}

Если не работает, необходимо проверить, является ли добавленный newlist правильным форматом данных.

=======================Обновление========================

В методе OnCreate, где метод обновления вызова _reportsHubConnector.ReportsRecieved изменяется следующим образом:

_reportsHubConnector.ReportsRecieved += (tmpReports) =>
{
    adapter.updateReportsList(tmpReports);

};

Измените аргумент reports на tmpReports, чтобы избежать смешивания с исходными данными reports.

Поэтому существует еще один распространенный способ обновления данных адаптера:

_reportsHubConnector.ReportsRecieved += (reports) =>
{
    List<IMobileReport> tmp = new List<IMobileReport>();
    tmp =  reports ; // use a tmp list data for updating , not using original list data 
    adapter.updateReportsList(tmp);

};

===========================Обновление===================== ==========

В моем примере проекта я нахожу интересное явление и, возможно, проблему.

Здесь я поделюсь своим собственным адаптером HomeScreenAdapter:

public class HomeScreenAdapter : BaseAdapter<TableItem> {
    List<TableItem> items;
    Activity context;
    public HomeScreenAdapter(Activity context, List<TableItem> items)
        : base()
    {
        this.context = context;
        this.items = new List<TableItem>();
        this.items.AddRange(items);
        //this.items = items;
    }
    public override long GetItemId(int position)
    {
        return position;
    }
    public override TableItem 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.CustomView, null);
        view.FindViewById<TextView>(Resource.Id.Text1).Text = item.Heading;
        view.FindViewById<TextView>(Resource.Id.Text2).Text = item.SubHeading+" items";
        view.FindViewById<ImageView>(Resource.Id.Image).SetImageResource(item.ImageResourceId);

        return view;
    }

    public void UpdateListView(List<TableItem> newTableItem)
    {
        items.Clear();
        items.AddRange(newTableItem);
        NotifyDataSetChanged();
    }
}

Вы увидите в Constructor HomeScreenAdapter , я прокомментировал эту строку кода this.items = items; . Результат, что это будет работать:

введите здесь описание изображения

Однако, если я использую this.items = items; вместо this.items.AddRange(items);, он ничего не обновит, даже не сможет ничего показать в ListView.

public HomeScreenAdapter(Activity context, List<TableItem> items)
    : base()
{
    this.context = context;
    this.items = new List<TableItem>();
    //this.items.AddRange(items);
    this.items = items;
}

Эффект :

введите здесь описание изображения

Возможная причина:

Если здесь используется знак равенства, адрес указателя элементов изменится. Когда данные обновляются, они не могут указывать на исходный источник данных, поэтому обновление не может быть успешным.

Поэтому здесь Constructor вашего кода можно изменить следующим образом, чтобы проверить, работает ли он:

public ReportsListViewAdapter(Context context, IEnumerable<IMobileReport> reports)
{
    //this.reports = reports.OrderBy(report => report.StudyDate).ToList();
    this.reports =  new List<IMobileReport>();
    this.reports.AddRange(reports.OrderBy(report => report.StudyDate).ToList());
    this.context = context;
    Filter = new ReportsFilter(this);
}

По теме . Вот ссылка на пример проекта< /а> .

person Junior Jiang    schedule 30.04.2020
comment
Окей, что за явление при обновлении? Появляется ли информация об ошибке или другая информация журнала? - person Junior Jiang; 30.04.2020
comment
Никаких ошибок не возникает после того, как я вызываю NotifyDataSetChanged, я вижу, что он запускает Count и Position адаптера, но представление не обновляется - person Max; 30.04.2020
comment
GetView не вызывается, поэтому, я думаю, он не обновляет представление. - person Max; 30.04.2020
comment
@Max Не могли бы вы поделиться кодом вызова метода обновления? - person Junior Jiang; 30.04.2020
comment
Я читал, что вам нужно вызвать RunOnUiThread, но когда я это делаю. RunOnUiThread не вызывается - person Max; 30.04.2020
comment
@Max Спасибо за обновление. Возможно, я знал, в чем проблема, я обновлю свой ответ. - person Junior Jiang; 30.04.2020
comment
@Max Я обновил ответ, вы можете проверить, работает ли он. Если нет, дайте мне знать об этом. - person Junior Jiang; 30.04.2020
comment
Это не сработало, я подозреваю, что это как-то связано с RunOnUiThread. Не грубите, в чем разница между использованием отчетов и переменной tmp, разве они не указывают на один и тот же объект? - person Max; 30.04.2020
comment
@Max Поток пользовательского интерфейса и другие потоки задач находятся в разных классах, они находятся в одном проекте. Однако, если вы хотите обновить пользовательский интерфейс, вам нужно сделать это в потоке пользовательского интерфейса, другой поток задач не будет работать. Вы можете попробовать с помощью RunOnUiThread вызвать метод обновления, чтобы проверить, работает ли он. - person Junior Jiang; 30.04.2020
comment
@Max Я тестирую на своем сайте с указанными данными, проблем нет. Если вы можете поделиться здесь ссылкой на пример проекта, я проверю это. - person Junior Jiang; 30.04.2020
comment
К сожалению, я не могу поделиться примером проекта, потому что это для стажировки. - person Max; 30.04.2020
comment
@ Макс Окей, понял. Позже я постараюсь поделиться ссылкой на образец проекта с указанными данными здесь для справки. - person Junior Jiang; 30.04.2020
comment
@Max Я проверил на локальном сайте и нашел причину, возможно, почему не могу обновить список. Я обновлю в ответ. - person Junior Jiang; 01.05.2020
comment
@Max Также обновите ссылку на образец проекта для справки. - person Junior Jiang; 01.05.2020