0

I wanne add new data to my listviewAdapter, i tried it with clearing all the data before it and notifying that there is now data but it doesn't seem to work. I followed the Solution (stackoverflow) but it doesn't work.

Does anyone have an idea why?

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);

        };
    }

When i debug slowly the GetView does get triggered, maybe this is a clue to why its not being called when i don't debug or go over the code quick.

This.RunOnUiThread is never called but update is.

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

            criticalButton.SetBackgroundColor(Android.Graphics.Color.Red);
        });
  };
Max
  • 120
  • 1
  • 9

1 Answers1

1

i tried it with clearing all the data before it and notifying that there is now data but it doesn't seem to work.

From shared code , not seeing clear method , you can add reports.Clear() to check whether it works .

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

If not works , need to check whehter added newlist is the correct data format.

========================Update========================

In OnCreate method , where _reportsHubConnector.ReportsRecieved call update method modify as follow :

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

};

Change reports argument to tmpReports to avoid mixing with the original data reports .

Therefore , there is another common way to update data of adapter as follow :

_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);

};

============================Update===============================

From my sample project , I find a interesting phenomenon and that maybe the problem.

Here I will share my custom adapter 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();
    }
}

You will see in the Constructor of HomeScreenAdapter , I commented this line of code this.items = items; . The reault that it will work:

enter image description here

However , if I use this.items = items; to replace this.items.AddRange(items);, it will update nothing even can not show anything in ListView .

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

The effect :

enter image description here

The possible reason :

If the equal sign is used here, the pointer address of the items will change. When the data is updated, it cannot point to the original data source, so the update cannot be successful.

Therefore , here Constructor of your code can modify as follow to check whehter it works :

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);
}

Related : Here is the sample project link .

Junior Jiang
  • 12,430
  • 1
  • 10
  • 30
  • Okey , what's the phenomenon when updating ? Whether occurs error info or other log info ? – Junior Jiang Apr 30 '20 at 07:03
  • No errors occur after i call the NotifyDataSetChanged, i do see he triggers Count and Position of the adapter but the view isn't update – Max Apr 30 '20 at 07:16
  • GetView doesn't get called so it doesn't update the view i guess – Max Apr 30 '20 at 07:27
  • @Max Could you share the code of where call the update method ? – Junior Jiang Apr 30 '20 at 07:29
  • I read that you need to call RunOnUiThread but when i do this.RunOnUiThread its not being called – Max Apr 30 '20 at 08:10
  • @Max Thanks for updating . Maybe I have known where problem is , I will update my answer . – Junior Jiang Apr 30 '20 at 08:14
  • @Max I have updated the answer , you can check that whether it works . If no let me know that . – Junior Jiang Apr 30 '20 at 08:27
  • It didn't work, i suspect it has something to do with the RunOnUiThread. Don't wanne be rude whats the diffrence between using reports and the tmp variable, don't they point to the same object? – Max Apr 30 '20 at 08:40
  • @Max The UI Thread and other task threads are in different therad , they are in the same project . However , if want to update UI , you need to do that in UI thread , other task thread will not work . You can have a try with `RunOnUiThread` to call update method to check whether it works also . – Junior Jiang Apr 30 '20 at 09:17
  • @Max I test in my site with specified data , that no problems .If can share a sample project link here , I will check that . – Junior Jiang Apr 30 '20 at 09:38
  • I can't share sample project sadly because its for an internship – Max Apr 30 '20 at 09:42
  • @Max Okey , got it . Later I will try to share a sample project link with specified data here for reference . – Junior Jiang Apr 30 '20 at 09:43
  • @Max I have tested in local site and find a reason , maybe why can not updating listview . I will update in answer . – Junior Jiang May 01 '20 at 07:45
  • @Max Also update with the sample project link for reference . – Junior Jiang May 01 '20 at 08:24