Xamarin.Forms CollectionView Infinite Scroll 在一段时间后冻结
Xamarin.Forms CollectionView Infinity Scroll freezed after sometime
我用带有 ItemSource=Photos
的 CollectionView 制作了一个滚动应用程序,在滚动一段时间后应用程序被冻结了。
这是我的 ViewModel
包含所有元素的构造函数代码:
public MainPageViewModel()
{
CounterData = 20;
StandartCounter = 20;
LoadPhotosCommand = new Command(execute: async () => await ExecuteGetAllPhotos());
LoadRefreshCommand = new Command(execute: async () => await ExecuteRefreshGetAllPhotos());
LoadNewPhotosCommand = new Command(execute: async () => await ExecuteGetNewPhotos());
LoadSelectedPhotoCommand = new Command(execute: async () => await ExecuteGetDetailsSelectedPhoto());
Photos = new ObservableCollection<Photo>();
PhotosAll = new ObservableCollection<Photo>();
PhotosModel = new PhotosModel();
SelectedPhoto = new Photo();
}
这是我在 ViewModel
中的逻辑,此函数从 API 中获取所有照片 - 将它们存储在 PhotosAll
列表中并向 [=14= 添加 20 个元素] list 是 collectionView 的 ItemSource:
async Task ExecuteGetAllPhotos()
{
if (IsBusy)
return;
try
{
IsBusy = true;
Photos.Clear();
PhotosAll.Clear();
PhotosModel = await InstagramCloneDataStore.GetAllPhotos();
if (PhotosModel != null)
{
foreach (var photo in PhotosModel.Photos)
{
PhotosAll.Add(photo);
}
foreach (var el in PhotosAll.Skip(0).Take(StandartCounter))
{
Photos.Add(el);
}
CounterData = StandartCounter;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
var msg = ex.Message;
}
finally
{
IsBusy = false;
}
}
这是 RemainingItemsThresholdReachedCommand
中的函数,逻辑是当用户滚动到 20 个项目时读取新的 20 个项目并将它们添加到 Photos
列表。
async Task ExecuteGetNewPhotos()
{
if (IsBusy)
return;
try
{
IsBusy = true;
await Task.Delay(100);
foreach (var el in PhotosAll.Skip(CounterData).Take(StandartCounter))
{
Photos.Add(el);
}
CounterData += StandartCounter;
}
catch (Exception ex)
{
Debug.WriteLine(ex);
var msg = ex.Message;
}
finally
{
IsBusy = false;
}
}
一开始滚动得很好,但过了一段时间应用程序就卡住了。有没有人有同样的问题?或者对此有一些解决方案?
更新
看起来 Photos
列表看起来更大加载新项目越来越慢
经过数小时的代码审查后,我学到了两件事:
- RemainingItemsThreshold="{Binding CounterData}" -> CounteData 是静态值,无法更改。
- 我为 skip 实现了一个值,或者你可以使用 CounterData 或者我使用
StandartCounter
,还有一个值用于计算我调用的大列表中的当前元素位置 RailCounter
。
每次你都从 PhotosAll.Skip(RailCounter).Take(StandartCounter)
和
RailCounter += StandartCounter;
问题是 CounterData 必须是静态的!
我用带有 ItemSource=Photos
的 CollectionView 制作了一个滚动应用程序,在滚动一段时间后应用程序被冻结了。
这是我的 ViewModel
包含所有元素的构造函数代码:
public MainPageViewModel()
{
CounterData = 20;
StandartCounter = 20;
LoadPhotosCommand = new Command(execute: async () => await ExecuteGetAllPhotos());
LoadRefreshCommand = new Command(execute: async () => await ExecuteRefreshGetAllPhotos());
LoadNewPhotosCommand = new Command(execute: async () => await ExecuteGetNewPhotos());
LoadSelectedPhotoCommand = new Command(execute: async () => await ExecuteGetDetailsSelectedPhoto());
Photos = new ObservableCollection<Photo>();
PhotosAll = new ObservableCollection<Photo>();
PhotosModel = new PhotosModel();
SelectedPhoto = new Photo();
}
这是我在 ViewModel
中的逻辑,此函数从 API 中获取所有照片 - 将它们存储在 PhotosAll
列表中并向 [=14= 添加 20 个元素] list 是 collectionView 的 ItemSource:
async Task ExecuteGetAllPhotos()
{
if (IsBusy)
return;
try
{
IsBusy = true;
Photos.Clear();
PhotosAll.Clear();
PhotosModel = await InstagramCloneDataStore.GetAllPhotos();
if (PhotosModel != null)
{
foreach (var photo in PhotosModel.Photos)
{
PhotosAll.Add(photo);
}
foreach (var el in PhotosAll.Skip(0).Take(StandartCounter))
{
Photos.Add(el);
}
CounterData = StandartCounter;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
var msg = ex.Message;
}
finally
{
IsBusy = false;
}
}
这是 RemainingItemsThresholdReachedCommand
中的函数,逻辑是当用户滚动到 20 个项目时读取新的 20 个项目并将它们添加到 Photos
列表。
async Task ExecuteGetNewPhotos()
{
if (IsBusy)
return;
try
{
IsBusy = true;
await Task.Delay(100);
foreach (var el in PhotosAll.Skip(CounterData).Take(StandartCounter))
{
Photos.Add(el);
}
CounterData += StandartCounter;
}
catch (Exception ex)
{
Debug.WriteLine(ex);
var msg = ex.Message;
}
finally
{
IsBusy = false;
}
}
一开始滚动得很好,但过了一段时间应用程序就卡住了。有没有人有同样的问题?或者对此有一些解决方案?
更新
看起来 Photos
列表看起来更大加载新项目越来越慢
经过数小时的代码审查后,我学到了两件事:
- RemainingItemsThreshold="{Binding CounterData}" -> CounteData 是静态值,无法更改。
- 我为 skip 实现了一个值,或者你可以使用 CounterData 或者我使用
StandartCounter
,还有一个值用于计算我调用的大列表中的当前元素位置RailCounter
。 每次你都从PhotosAll.Skip(RailCounter).Take(StandartCounter)
和RailCounter += StandartCounter;
问题是 CounterData 必须是静态的!