Xamarin.Формы реализуют отложенную загрузку в CollectionView

#c# #xamarin.forms #xamarin-community-toolkit #xamarin.forms.collectionview

#c# #xamarin.forms #xamarin-community-toolkit #xamarin.forms.collectionview — просмотр коллекции

Вопрос:

Это мой xaml-файл CollectionView:

     <ContentPage.Content>
        <Grid>
            <StackLayout>
                <RefreshView IsRefreshing="{Binding IsRefreshing, Mode=OneWay}"
             Command="{Binding LoadRefreshCommand}">
                    <CollectionView ItemsSource="{Binding Photos}" SelectedItem="{Binding SelectedPhoto}" RemainingItemsThreshold="10" RemainingItemsThresholdReachedCommand="{Binding LoadNewPhotosCommand}" >
                        <CollectionView.ItemTemplate>
                            <DataTemplate>
                                <Frame BorderColor="#3498DB">
                                    <Grid  RowSpacing="0" ColumnSpacing="0" Padding="0">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="*"/>
                                            <ColumnDefinition Width="3*"/>

                                        </Grid.ColumnDefinitions>
                                        <Grid.GestureRecognizers>
                                            <TapGestureRecognizer  Command="{Binding Source={x:Reference CurrentPage}, Path=BindingContext.LoadPhotosCommand}" />
                                        </Grid.GestureRecognizers>
                                        <Image Aspect="AspectFit" HeightRequest="50" Source="{Binding Url}"  Grid.Column="0"></Image>
                                        <Frame HasShadow="False" VerticalOptions="Center"  Grid.Column="1">
                                            <Label Text="{Binding Title}"></Label>
                                        </Frame>
                                    </Grid>
                                </Frame>
                            </DataTemplate>
                        </CollectionView.ItemTemplate>
                    </CollectionView>
                </RefreshView>
            </StackLayout>
            <StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="Center">
                <Frame IsVisible="{Binding IsBusy}" BorderColor="#3498DB" HasShadow="False" BackgroundColor="#eeeeee">
                    <StackLayout>
                        <ActivityIndicator IsVisible="{Binding IsBusy}" IsRunning="{Binding IsBusy}" HorizontalOptions="Center" VerticalOptions="Center"></ActivityIndicator>
                        <Label TextColor="#3498DB" Text="Loading Data, Please Wait..." HorizontalTextAlignment="Center" VerticalTextAlignment="Center" HorizontalOptions="Center" VerticalOptions="Center" IsVisible="{Binding IsBusy}"/>
                    </StackLayout>
                </Frame>
            </StackLayout>
        </Grid>
    </ContentPage.Content>
 

Это конструктор в ViewModel:

         public MainPageViewModel()
        {
            LoadPhotosCommand = new Command(execute: async () => await ExecuteGetAllPhotos());
            LoadRefreshCommand = new Command(execute: async () => await ExecuteRefreshGetAllPhotos());
            LoadRefreshCommand = new Command(execute: async () => await ExecuteGetNewPhotos());
            Photos = new ObservableCollection<Photo>();
            PhotosModel = new PhotosModel();
            SelectedPhoto = new Photo();
        }
 

Это код в ViewModel, как я получаю данные:

         async Task ExecuteGetAllPhotos()
        {
            if (IsBusy)
                return;      
            try
            {
                IsBusy = true;
                Photos.Clear();
                PhotosModel = await InstagramCloneDataStore.GetAllPhotos();
               if(PhotosModel!=null)
                {
                    foreach (var photo in PhotosModel.Photos)
                    {
                       Photos.Add(photo);                      
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
                var msg = ex.Message;
            }
            finally
            {
                IsBusy = false;
            }
        }
 

Этот код отлично работает при чтении 100 200 500 записей данных.Но когда я прочитал 5000 записей данных, приложение зависло и захотело сделать принудительную остановку. Для отображения данных требуется около 2-3 минут. Поэтому я хочу реализовать некоторую логику для отложенной загрузки или бесконечной прокрутки.
Это командная функция RemainingItemsThresholdReachedCommand , и логика должна быть записана для прокрутки данных:

         async Task ExecuteGetNewPhotos()
        {
            if (IsBusy)
                return;
            try
            {
//some logic here---------->
                IsBusy = true;
                Photos.Clear();
                PhotosModel = await InstagramCloneDataStore.GetAllPhotos();
                if (PhotosModel != null)
                {
                    foreach (var photo in PhotosModel.Photos)
                    {          
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
                var msg = ex.Message;
            }
            finally
            {
                IsBusy = false;
            }
        }
 

Я не понимаю, как работает ленивая загрузка или прокрутка. Кто-нибудь может помочь?

Комментарии:

1. вы просто предоставляете функцию, которая загружает X следующих строк данных и добавляет их в вашу ObservableCollection. Документы объясняют это довольно четко — docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface /…

2. Я не могу понять, как

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

4. @Jason у меня есть ObservableCollection<Фото> список, который считывается из API. когда RemainingItemsThresholdReachedCommand="{Binding LoadNewPhotosCommand}" вызывается, что делать со списком?

5. загрузите дополнительные данные из вашего сервиса, а затем добавьте их в ObservableCollection

Ответ №1:

Когда ваша страница загружается, вы должны вызвать свою службу, чтобы загрузить первые X строк данных. Скажем так X=50 — это может быть любое значение, которое вы хотите.

Когда пользователь прокручивает список до конца, CollectionView он срабатывает RemainingItemsThresholdReachedCommand . Когда это сработает, вы должны извлечь следующее X количество элементов из своего сервиса и добавить их в свой ItemsSource .

Чтобы это сработало, ваш сервис должен быть способен постепенно загружать данные.

Комментарии:

1. У меня есть один ObservableCollection AllPhotos с 5000 записями данных. И создайте другого ObservableCollection PhotoSequence , который может получать 50 элементов AllPhotos каждый раз и привязываться к источнику CollectionView. Это твоя идея?

2. нет, получение 5000 элементов одновременно — это то, что заставляет ваше приложение зависать. Прекрати это делать. Вместо этого используйте инкрементную загрузку, чтобы запрашивать их порциями, чтобы повысить производительность.

3. сначала я должен получить все элементы из API. То есть быстро, медленная часть — это рендеринг всех 5000 элементов

4. Я не могу понять, как получать данные из API последовательно. Ты пытаешься сказать мне, что

5. Хорошо, тогда попробуйте то, что вы предложили в ПЕРВОМ комментарии.