Имеется сервер приложения который находится "где-то" в Интернет. Приложение соответственно работает с этим сервером. На сервере есть список объектов, на клиенте есть ListView, который призван отображать этот список. Сервер на запрос клиента возвращает список элементов в JSon.
Задача:
- обеспечить заполнение ListView порционно, т.е. сразу не грузить весь список объектов с сервера, а только видимые элементы и при прокрутке списка догружать
Сделал наследника от BaseAdapter:
(код на C#, но я думаю никого это не смутит)
Код: Выделить всё
public class FacilityListViewAdapter : BaseAdapter
{
private readonly LayoutInflater _inflater;
private readonly int _typeId;
private List<Facility> list = new List<Facility>();
public FacilityListViewAdapter(int countItems,LayoutInflater inflater, int typeId)
{
_inflater = inflater;
_typeId = typeId;
for (int i = 0; i < countItems; i++)
{
list.Add(new Facility());
}
}
public override Java.Lang.Object GetItem(int position)
{
return null;
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View vi = convertView;
if (vi == null)
{
vi = _inflater.Inflate(Resource.Layout.FacilityItem, null);
}
else
{
return vi;
}
LinearLayout llData = vi.FindViewById<LinearLayout>(Resource.Id.llData);
llData.Visibility = ViewStates.Invisible;
LinearLayout llLoading = vi.FindViewById<LinearLayout>(Resource.Id.llLoading);
llLoading.Visibility = ViewStates.Visible;
TextView tvFacilityTitle = vi.FindViewById<TextView>(Resource.Id.tvFacilityTitle);
TextView tvFacilityId = vi.FindViewById<TextView>(Resource.Id.tvFacilityId);
ImageView ivLogo = vi.FindViewById<ImageView>(Resource.Id.ivLogo);
TextView tvRating = vi.FindViewById<TextView>(Resource.Id.tvRating);
TextView tvWorkTime = vi.FindViewById<TextView>(Resource.Id.tvWorkTime);
TextView tvWorkTimeState = vi.FindViewById<TextView>(Resource.Id.tvWorkTimeState);
BackgroundWorker background = new BackgroundWorker();
background.DoWork += (sender, args) =>
{
if (list[position].Id == 0)
{
ResponseObject responseObject =
FacilityProvider.Instance.GetFacilitiesByType(App.Instance.UserId, _typeId,
string.Empty, list[position].Id, 1);
if (responseObject != null)
{
if (responseObject.State != ResponseObject.StateResponse.Fail)
{
var facilities = ((List<Facility>) responseObject.Data);
if (facilities.Count > 0)
{
list[position] = facilities[0];
}
}
else
{
return;
}
}
}
if (list[position].Id > 0)
{
int rating = RatingProvider.Instance.GetRating(App.Instance.UserId, list[position].Id,
OwnerTypes.Facility);
args.Result = rating;
}
};
background.RunWorkerCompleted += (sender, args) =>
{
tvFacilityTitle.Text = list[position].Title;
tvFacilityId.Text = list[position].Id.ToString();
UrlImageViewHelper.UrlImageViewHelper.SetUrlDrawable((ivLogo),
ServerProvider.App.Instance.ServerImageUrl + list[position].IconURL);
if (args.Result != null)
{
tvRating.Text = args.Result.ToString();
}
else
{
tvRating.Text = "0";
}
tvWorkTime.Text =
string.Format("{0}-{1}", list[position].WorkTimeStart.ToString("t"),
list[position].WorkTimeEnd.ToString("t"));
var now = DateTime.Now;
if (now.TimeOfDay >= list[position].WorkTimeStart.TimeOfDay &&
now.TimeOfDay <= list[position].WorkTimeEnd.TimeOfDay)
{
tvWorkTimeState.Text = "Открыто";
tvWorkTimeState.SetTextColor(Android.Graphics.Color.Green);
}
else
{
tvWorkTimeState.Text = "Закрыто";
tvWorkTimeState.SetTextColor(Android.Graphics.Color.Red);
}
llLoading.Visibility = ViewStates.Invisible;
llData.Visibility = ViewStates.Visible;
};
background.RunWorkerAsync(position);
return vi;
}
public override int Count
{
get { return list.Count; }
}
public void SetNewCount(int count)
{
if (count > list.Count)
{
for (int i = 0; i < count - list.Count; i++)
{
list.Add(new Facility());
}
}
this.NotifyDataSetChanged();
}
}
В принципе код задачу свою выполняет, НО по какой-то неизвестной мне причине, в списке дублируются элементы, хаотичный порядок и при прокрутке списка "туда - сюда" порядок элементов меняется. Я подозреваю что дело в параметре position метода GetView, но что конкретно не могу разобраться.
Подскажите пожалуйста что я делаю не так, может использую не тот адаптер или не понимаю принцип работы метода GetView, а может вообще "изобретаю велосипед" и все давно уже сделано?