Wyświetl listy z podziałem na strony

Ten przewodnik uzupełnia omówienie biblioteki tymczasowej, w którym wyjaśnia, jak przedstawiać użytkownikom listy informacji w interfejsie aplikacji, zwłaszcza w przypadku zmiany tych informacji.

Łączenie interfejsu użytkownika z modelem widoku

Możesz połączyć wystąpienie LiveData<PagedList> z PagedListAdapter, jak pokazano w tym fragmencie kodu:

Kotlin

class ConcertActivity : AppCompatActivity() {
    private val adapter = ConcertAdapter()

    // Use the 'by viewModels()' Kotlin property delegate
    // from the activity-ktx artifact
    private val viewModel: ConcertViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState);
        viewModel.concerts.observe(this, Observer { adapter.submitList(it) })
    }
}

Java

public class ConcertActivity extends AppCompatActivity {
    private ConcertAdapter adapter = new ConcertAdapter();
    private ConcertViewModel viewModel;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        viewModel = new ViewModelProvider(this).get(ConcertViewModel.class);
        viewModel.concertList.observe(this, adapter::submitList);
    }
}

Gdy źródła danych udostępniają nowe instancje PagedList, aktywność wysyła te obiekty do adaptera. Implementacja PagedListAdapter określa sposób obliczania aktualizacji i automatycznie obsługuje stronicowanie i różnicowanie list. Dlatego ViewHolder musi powiązać tylko konkretny udostępniony element:

Kotlin

class ConcertAdapter() :
        PagedListAdapter<Concert, ConcertViewHolder>(DIFF_CALLBACK) {
    override fun onBindViewHolder(holder: ConcertViewHolder, position: Int) {
        val concert: Concert? = getItem(position)

        // Note that "concert" is a placeholder if it's null.
        holder.bindTo(concert)
    }

    companion object {
        private val DIFF_CALLBACK = ... // See Implement the diffing callback section.
    }
}

Java

public class ConcertAdapter
        extends PagedListAdapter<Concert, ConcertViewHolder> {
    protected ConcertAdapter() {
        super(DIFF_CALLBACK);
    }

    @Override
    public void onBindViewHolder(@NonNull ConcertViewHolder holder,
            int position) {
        Concert concert = getItem(position);

        // Note that "concert" can be null if it's a placeholder.
        holder.bindTo(concert);
    }

    private static DiffUtil.ItemCallback<Concert> DIFF_CALLBACK
            = ... // See Implement the diffing callback section.
}

PagedListAdapter obsługuje zdarzenia wczytywania strony za pomocą obiektu PagedList.Callback. Gdy użytkownik przewija stronę, PagedListAdapter wywołuje metodę PagedList.loadAround(), by przekazać informacje do bazowego komponentu PagedList, które wskazują, które elementy należy pobrać z DataSource.

Implementowanie różniącego się wywołania zwrotnego

Poniższy przykład pokazuje ręczną implementację funkcji areContentsTheSame(), która porównuje odpowiednie pola obiektów:

Kotlin

private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Concert>() {
    // The ID property identifies when items are the same.
    override fun areItemsTheSame(oldItem: Concert, newItem: Concert) =
            oldItem.id == newItem.id

    // If you use the "==" operator, make sure that the object implements
    // .equals(). Alternatively, write custom data comparison logic here.
    override fun areContentsTheSame(
            oldItem: Concert, newItem: Concert) = oldItem == newItem
}

Java

private static DiffUtil.ItemCallback<Concert> DIFF_CALLBACK =
        new DiffUtil.ItemCallback<Concert>() {

    @Override
    public boolean areItemsTheSame(Concert oldItem, Concert newItem) {
        // The ID property identifies when items are the same.
        return oldItem.getId() == newItem.getId();
    }

    @Override
    public boolean areContentsTheSame(Concert oldItem, Concert newItem) {
        // Don't use the "==" operator here. Either implement and use .equals(),
        // or write custom data comparison logic here.
        return oldItem.equals(newItem);
    }
};

Adapter zawiera definicję porównywania elementów, dlatego automatycznie wykrywa zmiany w tych elementach po wczytaniu nowego obiektu PagedList. W efekcie adapter aktywuje wydajne animacje elementów w obiekcie RecyclerView.

Różnice w przypadku użycia innego typu przejściówki

Jeśli nie zdecydujesz się na dziedziczenie z PagedListAdapter, np. gdy używasz biblioteki, która ma własny adapter, nadal możesz korzystać z funkcji różnicowania adaptera biblioteki, pracując bezpośrednio z obiektem AsyncPagedListDiffer.

Umieszczanie obiektów zastępczych w interfejsie

Jeśli chcesz, aby przed zakończeniem pobierania danych aplikacja wyświetlała listę, możesz pokazać użytkownikom zastępcze elementy listy. PagedList obsługuje ten przypadek, prezentując dane elementu listy jako null, dopóki nie zostaną one wczytane.

Obiekty zastępcze mają te zalety:

  • Obsługa pasków przewijania: PagedList podaje liczbę elementów listy w elemencie PagedListAdapter. Ta informacja umożliwia adapterowi narysowanie paska przewijania z pełnym rozmiarem listy. Przy wczytywaniu nowych stron pasek przewijania nie skacze, ponieważ lista nie zmienia się.
  • Wskaźnik wczytywania nie jest wymagany: rozmiar listy jest już znany, więc nie trzeba powiadamiać użytkowników o wczytywaniu kolejnych elementów. Symbole zastępcze same w sobie przekazują te informacje.

Zanim jednak dodasz obsługę obiektów zastępczych, pamiętaj o tych warunkach wstępnych:

  • Wymaga obliczonego zbioru danych: instancje DataSource z biblioteki trwałości sal mogą skutecznie zliczać elementy. Jeśli jednak korzystasz z niestandardowego rozwiązania do pamięci lokalnej lub architektury danych obejmującej tylko sieć, określenie, ile elementów składa się na zbiór danych, może być kosztowne, a nawet niemożliwe.
  • Wymaga adaptera, by uwzględnić niewczytane elementy: adapter lub mechanizm do prezentacji, którego używasz do przygotowywania listy pod kątem inflacji do obsługi pustych elementów listy. Gdy na przykład łączysz dane z elementem ViewHolder, musisz podać wartości domyślne reprezentujące dane niewczytane.
  • Wymaga wyświetleń elementów w tym samym rozmiarze: jeśli rozmiary elementów listy mogą się zmieniać w zależności od ich treści (np. aktualizacji w sieciach społecznościowych), przenikanie między elementami nie wygląda dobrze. W tym przypadku zdecydowanie zalecamy wyłączenie obiektów zastępczych.

Prześlij opinię

Podziel się z nami swoją opinią i pomysłami, korzystając z tych zasobów:

Śledzenie problemów
Zgłoś problemy, żebyśmy mogli naprawić błędy.

Dodatkowe materiały

Więcej informacji o bibliotece stronicowania znajdziesz w tych materiałach:

Próbki

Ćwiczenia z programowania

Filmy