2017-01-10 13 views
1

リクエストごとにサーバーから一度に10アイテムずつロードするリクエストを作成しようとしています。たとえば、ユーザーがボタンをクリックして次のページにリダイレクトするとき、最初の10項目が最初に表示され、他の項目の要求はバックグラウンドで行われます。これを行うにはどうしたらいいですか?返される最大数と各リクエストの開始位置から設定することで、サーバー側でどのように動作するのかを知ることができますが、これを見るのは正しい方法ですか?結果ごとに10アイテムずつデータをロードするXamarinフォーム

答えて

3

はい、それはそれを処理する良い方法のようです。これはしばしばデータの「ページネーション」と呼ばれます。

あなたのAPIに、受信したいデータの「ページ」と、そのページに返すアイテムの最大数(ページング数)のカウントを処理しますか?ここでは、これをForms用に実装する方法の例を示します。

あなたのViewModelを実装するための契約:

public interface ISupportIncrementalLoading 
{ 
    int PageSize { get; set; } 

    bool HasMoreItems { get; set; } 

    bool IsLoading { get; } 

    Task LoadMoreItemsAsync(); 
} 

のViewModelでの実装例:

#region ISupportIncrementalLoading Implementation 

public int PageSize { get; set; } = 10; 

public bool HasMoreItems { get; set; } 

public async Task LoadMoreItemsAsync() 
{ 
    await LoadMoreItemsCommand.ExecuteAsyncTask(); 
} 

//... 

#endregion 

例LoadMoreItemsCommand:

LoadMoreItemsCommand = new Command(async() => 
{ 
    int fetchOffset = Requests.Count; 
    int fetchMax = PageSize; 

    // "Pagination" of your API request starting at the offset 
    // and getting a maximum of the `fetchMax` or "page size" 
    Results = await GetRequestsAsync(fetchOffset, fetchMax); 
}); 

ListViewのようなコントロールでこれを自動的にサポートするには、レンダラーまたは「エフェクト」をカスタマイズしてこれを行うことができます。これはthisプラグインからの技術を活用し

// Custom ListViewRenderer, iOS example 
public class IncrementalListViewRenderer : ListViewRenderer 
{ 
    public IncrementalListViewRenderer() 
    { 
    } 

    protected override void OnElementChanged(ElementChangedEventArgs<ListView> e) 
    { 
     base.OnElementChanged(e); 

     if (Control != null) 
     { 
      // Need to customize the source but not lose existing functionality so 
      // we need a copy of it to use 
      UITableViewSource defaultSource = Control.Source;    
      Control.Source = new IncrementalDataSource(Element as IncrementalListView, defaultSource);    
     } 
    } 

    class IncrementalDataSource : UITableViewSource 
    { 
     readonly UITableViewSource existingSource; 
     readonly IncrementalListView listView; 
     readonly ISupportIncrementalLoading incrementalLoading; 

     int lastPosition; 
     int preloadMargin = 5; 

     public IncrementalDataSource(IncrementalListView listView, UITableViewSource existingSource) 
     { 
      this.listView = listView; 
      this.existingSource = existingSource; 

      incrementalLoading = listView.BindingContext as ISupportIncrementalLoading; 

      lastPosition = 0; 

      LoadMoreItems(); 
     } 

     public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath) 
     { 
      int position = indexPath.Row; 
      var itemsSource = listView.ItemsSource as IList; 

      if (itemsSource != null) 
      { 
       int preloadIndex = Math.Max(itemsSource.Count - preloadMargin, 0); 

       if ((position > lastPosition || (position == itemsSource.Count - 1)) && (position >= preloadIndex)) 
       { 
        lastPosition = position; 

        if(!incrementalLoading.IsLoading && incrementalLoading.HasMoreItems) 
         LoadMoreItems(); 
       } 
      } 

      var cell = existingSource.GetCell(tableView, indexPath); 
      cell.SelectionStyle = UITableViewCellSelectionStyle.None; 

      return cell; 
     } 

     public override void RowSelected(UITableView tableView, NSIndexPath indexPath) 
     { 
      existingSource.RowSelected(tableView, indexPath); 
     } 

     public override nint RowsInSection(UITableView tableview, nint section) 
     { 
      return existingSource.RowsInSection(tableview, section); 
     } 

     void LoadMoreItems() 
     { 
      // Note the use of Nito.AsyncEx lib 
      INotifyTaskCompletion taskCompletion = NotifyTaskCompletion.Create(LoadMoreItemsAsync()); 
     } 

     public async Task LoadMoreItemsAsync() 
     { 
      await incrementalLoading.LoadMoreItemsAsync(); 
     } 
    } 
} 

:ここで剪定の例です。

関連する問題