Pazartesi Ocak 28th, 2019

Xamarin Forms Lazy Loading(Infinite Scroll)

ile Ebubekir Sezer

Uygulama yaparken görüntünün daha iyi gözükmesi için veya kullanıcıya yaptığı işlemlerinin gerçekleştiğini göstermek için bazı özelleştirmelere yapabiliriz, Bunlardan biride lazy loading (infinite scroll) adı verilen bir işlemdir. Lazy loading list view kullanırken kullanıcıdan belirli sayıda item gösterirken diger itemleri göstermek istediğimizde aşağı dogru telefonda işlem yaptığımızda kullanıcıya yükleniyor diyerekten belirli sayıda item’i tekrar karşısına getirme işlemidir.

Lazy loading’i kullanmak için basit bir uygulama yapacağım bu uygulama’da bazı futbolcular olacak ve bu futbolcuların resimleri isimleri ve hangi takımda oynadıklarını gösteren bir uygulama olacak bir class oluşturup bu class’ın içine degişkenlerimi tanıtıyorum daha sonra bu class’dan bir liste oluşturup verilerimi atıyorum daha sonra şöyle bir fonskiyon yazıyorum;

 public async Task<List<Player>> GetItemAsync(int pageIndex,int pagesize)
        {
            await Task.Delay(2000);
            return players.Skip(pageIndex * pagesize).Take(pagesize).ToList();
        }

Bu fonksiyon sayesinde sayfada kaç tane kullanıcı olacağını alıp daha sonra kullanıların liste biçimde dönüş yapılmasını sağlıyorum. Uygulamamın pcl kısmına Xamarin.Forms.Extended.InfiniteScrolling nugetini ekliyorum, daha sonra ana sayfama bind edeceğim bir model atıyorum bu model benim ana sayfamın modeli olacak bu class’ı INotifyPropertyChanged interfacesinden kalıtım alarak oluşturuyorum. Classın içerisine şu kod dizimini yazıyorum;

private bool _isBusy;
        private const int PageSize = 10;
        readonly DataService dataService = new DataService();

        public event PropertyChangedEventHandler PropertyChanged;

        public InfiniteScrollCollection<Player> Players { get; set; }
            
        public bool IsBusy
        {
            get => _isBusy;
            set
            {
                _isBusy = value;
                OnPropertyChanged();
            }
        }
        public MainViewModel()
        {
            Players = new InfiniteScrollCollection<Player>
            {
                OnLoadMore = async () =>
                 {
                     IsBusy = true;
                     var page = Players.Count / PageSize;
                     var player = await dataService.GetItemAsync(page, PageSize);
                     IsBusy = false;
                     return player;
                 },
                OnCanLoadMore = () =>
                {
                    return Players.Count < 50;
                }
            };
            DownloadDataAsync();
        }
        private async Task DownloadDataAsync()
        {
            var items = await dataService.GetItemAsync(pageIndex: 0, pagesize: PageSize);
            Players.AddRange(items);
        }
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyname=null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname));
        }

Bu kodun içerisinde bool isbusy kullanarak kullanıcının hareketini kontrol ettirerek ekranda neler çıkacağına karar verdiriyorum, yukarıda gördüğünüz gibi sayfama 10 tane item olacağınıda belirtmişim ve veri servisimden bir tane obje oluşturup bunu yeni veri servisim olarak kullanıyorum tabi birde InfiniteScrollCollection<Player> Players kullanarak oyuncular nesnesi oluşturuyorum daha sonra bunun içerisinde bazı kontrolleri kullanarak işlemler yaptırıyorum ve bu işlemleri yaparken bazı fonksiyonlar yardımı ile yapıyorum DownloadDataAsync() fonksiyonu ile veri servisinden bu oyuncunun hangi sayfada kaçıncı item’i olacağını belirtip geri döndüren fonskiyon oluyor. En son olarak’da basit bir tasarım oluşturup ekrana oyuncuları bastırıyorum.

<ContentPage.BindingContext>
        <local:MainViewModel/>
    </ContentPage.BindingContext>
    <StackLayout>
        <Label Text="PLAYERS"
               TextColor="Black"
               FontSize="Large"
               VerticalOptions="Center"
               HorizontalOptions="Center"/>
        <ListView ItemsSource="{Binding Players}"
                  CachingStrategy="RecycleElement"
                  HasUnevenRows="True">
            <ListView.Behaviors>
                <extended:InfiniteScrollBehavior IsLoadingMore="{Binding IsBusy}"/>
            </ListView.Behaviors>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid Padding="10,10">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="0.4*"/>
                                <ColumnDefinition Width="0.6*"/>
                            </Grid.ColumnDefinitions>
                            <Image Source="{Binding Image}"
                                   Grid.Column="0"
                               VerticalOptions="Center"
                               HorizontalOptions="StartAndExpand"
                                   WidthRequest="100"
                                   HeightRequest="100"
                               Aspect="AspectFit"/>
                            <Grid Grid.Column="1" VerticalOptions="Center" HorizontalOptions="Start">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="0.7*"/>
                                    <RowDefinition Height="0.3*"/>
                                </Grid.RowDefinitions>
                                <Label Text="{Binding Name}"
                                   Grid.Row="0"
                                       VerticalOptions="Center"
                                       HorizontalOptions="Start"
                               FontSize="Medium"
                               TextColor="Black"/>
                                <Label Text="{Binding Club}"
                                       Grid.Row="1"
                                       FontSize="Small"
                                       TextColor="Black"
                                       VerticalOptions="Start"
                                       HorizontalOptions="Start"/>
                            </Grid>
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
            <ListView.Footer>
                <Grid IsVisible="{Binding IsBusy}">
                    <Grid.Triggers>
                        <Trigger TargetType="Grid"
                                 Property="IsVisible"
                                 Value="False">
                            <Setter Property="HeightRequest"
                                    Value="0"/>
                        </Trigger>
                    </Grid.Triggers>
                    <Label Text="Loading..."
                           TextColor="Green"
                           VerticalOptions="Center"
                           HorizontalOptions="Center"
                           FontAttributes="Bold"
                           FontSize="Medium"/>
                </Grid>
            </ListView.Footer>
        </ListView>
    </StackLayout>

Bu tasarımıda yaptıktan sonra uygulamamız şöyle bir tasarım ve görünüm oluşuyor;