更新自定义列表视图适配器
Update custom listviewAdapter
我想向我的 listviewAdapter 添加新数据,我尝试清除它之前的所有数据并通知现在有数据,但它似乎不起作用。我遵循了 Solution (Whosebug) 但它不起作用。
有人知道为什么吗?
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 从未被调用,但更新被调用。
_reportsHubConnector.ReportsRecieved += (tmpReports) =>
{
adapter.updateReportsList(tmpReports);
this.RunOnUiThread(() =>
{
criticalButton.SetBackgroundColor(Android.Graphics.Color.Red);
});
};
i tried it with clearing all the data before it and notifying that there is now data but it doesn't seem to work.
来自共享代码,没有看到明确的方法,您可以添加 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();
}
}
你会看到在HomeScreenAdapter的Constructor
中,我注释了这行代码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);
}
相关:这里是the sample project link.
我想向我的 listviewAdapter 添加新数据,我尝试清除它之前的所有数据并通知现在有数据,但它似乎不起作用。我遵循了 Solution (Whosebug) 但它不起作用。
有人知道为什么吗?
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 从未被调用,但更新被调用。
_reportsHubConnector.ReportsRecieved += (tmpReports) =>
{
adapter.updateReportsList(tmpReports);
this.RunOnUiThread(() =>
{
criticalButton.SetBackgroundColor(Android.Graphics.Color.Red);
});
};
i tried it with clearing all the data before it and notifying that there is now data but it doesn't seem to work.
来自共享代码,没有看到明确的方法,您可以添加 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();
}
}
你会看到在HomeScreenAdapter的Constructor
中,我注释了这行代码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);
}
相关:这里是the sample project link.