Bu belgede, Sayfalama Kitaplığı'na genel bakış bölümünde anlatılanlar temel alınarak uygulamanızın veri yükleme çözümünü, uygulamanızın mimari ihtiyaçlarını karşılayacak şekilde nasıl özelleştirebileceğiniz açıklanmaktadır.
Gözlemlenebilir bir liste oluşturma
Kullanıcı arayüzü kodunuz genellikle uygulamanızın ViewModel sınıfında bulunan bir LiveData<PagedList> nesnesini (veya RxJava2 kullanıyorsanız Flowable<PagedList> ya da Observable<PagedList> nesnesini) gözlemler.
Bu gözlemlenebilir nesne, uygulamanızın liste verilerinin sunumu ve içeriği arasında bir bağlantı oluşturur.
Bu gözlemlenebilir PagedList nesnelerinden birini oluşturmak için bir LivePagedListBuilder veya RxPagedListBuilder nesnesine DataSource.Factory örneği iletin. DataSource nesnesi, tek bir PagedList için sayfaları yükler. Fabrika sınıfı, veritabanı tablosu geçersiz kılmaları ve ağ yenilemeleri gibi içerik güncellemelerine yanıt olarak yeni PagedList örnekleri oluşturur. Room kalıcılık kitaplığı sizin için DataSource.Factory nesneleri sağlayabilir veya kendi nesnelerinizi oluşturabilirsiniz.
Aşağıdaki kod snippet'inde, Room'un DataSource.Factory oluşturma özelliklerini kullanarak uygulamanızın ViewModel sınıfında yeni bir LiveData<PagedList> örneğinin nasıl oluşturulacağı gösterilmektedir:
ConcertDao
Kotlin
@Dao
interface ConcertDao {
// The Int type parameter tells Room to use a PositionalDataSource
// object, with position-based loading under the hood.
@Query("SELECT * FROM concerts ORDER BY date DESC")
fun concertsByDate(): DataSource.Factory<Int, Concert>
}
Java
@Dao
public interface ConcertDao {
// The Integer type parameter tells Room to use a PositionalDataSource
// object, with position-based loading under the hood.
@Query("SELECT * FROM concerts ORDER BY date DESC")
DataSource.Factory<Integer, Concert> concertsByDate();
}
ConcertViewModel
Kotlin
// The Int type argument corresponds to a PositionalDataSource object.
val myConcertDataSource : DataSource.Factory<Int, Concert> =
concertDao.concertsByDate()
val concertList = myConcertDataSource.toLiveData(pageSize = 50)
Java
// The Integer type argument corresponds to a PositionalDataSource object.
DataSource.Factory<Integer, Concert> myConcertDataSource =
concertDao.concertsByDate();
LiveData<PagedList<Concert>> concertList =
LivePagedListBuilder(myConcertDataSource, /* page size */ 50).build();
Kendi sayfalama yapılandırmanızı tanımlama
İleri seviye kullanım alanları için LiveData<PagedList>'ı daha ayrıntılı şekilde yapılandırmak isterseniz kendi sayfalama yapılandırmanızı da tanımlayabilirsiniz. Özellikle aşağıdaki özellikleri
tanımlayabilirsiniz:
- Sayfa boyutu: Her sayfadaki öğe sayısı.
- Önceden getirme mesafesi: Bir uygulamanın kullanıcı arayüzündeki son görünür öğe göz önüne alındığında, Sayfalama Kitaplığı'nın önceden getirmeye çalışması gereken, bu son öğeden sonraki öğelerin sayısıdır. Bu değer, sayfa boyutundan birkaç kat daha büyük olmalıdır.
- Yer tutucu varlığı: Kullanıcı arayüzünün, henüz yüklenmemiş liste öğeleri için yer tutucu gösterip göstermeyeceğini belirler. Yer tutucu kullanmanın avantajları ve dezavantajları hakkında bilgi edinmek için Kullanıcı arayüzünüzde yer tutucu sağlama başlıklı makaleyi inceleyin.
Sayfalama Kitaplığı'nın uygulamanızın veritabanından bir listeyi ne zaman yükleyeceği konusunda daha fazla kontrol sahibi olmak istiyorsanız aşağıdaki kod snippet'inde gösterildiği gibi LivePagedListBuilder öğesine özel bir Executor nesnesi iletin:
ConcertViewModel
Kotlin
val myPagingConfig = Config(
pageSize = 50,
prefetchDistance = 150,
enablePlaceholders = true
)
// The Int type argument corresponds to a PositionalDataSource object.
val myConcertDataSource : DataSource.Factory<Int, Concert> =
concertDao.concertsByDate()
val concertList = myConcertDataSource.toLiveData(
pagingConfig = myPagingConfig,
fetchExecutor = myExecutor
)
Java
PagedList.Config myPagingConfig = new PagedList.Config.Builder()
.setPageSize(50)
.setPrefetchDistance(150)
.setEnablePlaceholders(true)
.build();
// The Integer type argument corresponds to a PositionalDataSource object.
DataSource.Factory<Integer, Concert> myConcertDataSource =
concertDao.concertsByDate();
LiveData<PagedList<Concert>> concertList =
new LivePagedListBuilder<>(myConcertDataSource, myPagingConfig)
.setFetchExecutor(myExecutor)
.build();
Doğru veri kaynağı türünü seçme
Kaynak verilerinizin yapısını en iyi şekilde işleyen veri kaynağına bağlanmanız önemlidir:
- Yüklediğiniz sayfalarda sonraki veya önceki tuşları yerleştirilmişse
PageKeyedDataSourcekullanın. Örneğin, ağdan sosyal medya gönderileri getiriyorsanız bir yüklemedekinextPagejetonunu sonraki bir yüklemeye aktarmanız gerekebilir. - N+1 öğesini getirmek için N öğesindeki verileri kullanmanız gerekiyorsa
ItemKeyedDataSourcekullanın. Örneğin, bir tartışma uygulaması için dizi haline getirilmiş yorumları getiriyorsanız sonraki yorumun içeriğini almak için son yorumun kimliğini iletmeniz gerekebilir. - Veri deponuzda seçtiğiniz herhangi bir konumdan veri sayfaları getirmeniz gerekiyorsa
PositionalDataSourcekullanın. Bu sınıf, seçtiğiniz konumdan başlayan bir veri öğesi kümesi istemeyi destekler. Örneğin, istek 1500. konumdan başlayan 50 veri öğesini döndürebilir.
Veriler geçersiz olduğunda bildir
Paging kitaplığını kullanırken bir tablonun veya satırın eski hâle geldiğini uygulamanızın diğer katmanlarına bildirmek veri katmanının sorumluluğundadır. Bunu yapmak için uygulamanız için seçtiğiniz DataSource sınıfından invalidate() yöntemini çağırın.
Kendi veri kaynaklarınızı oluşturma
Özel bir yerel veri çözümü kullanıyorsanız veya verileri doğrudan bir ağdan yüklüyorsanız DataSource alt sınıflarından birini uygulayabilirsiniz. Aşağıdaki kod snippet'i, belirli bir konserin başlangıç zamanına göre anahtarlanmış bir veri kaynağını göstermektedir:
Kotlin
class ConcertTimeDataSource() :
ItemKeyedDataSource<Date, Concert>() {
override fun getKey(item: Concert) = item.startTime
override fun loadInitial(
params: LoadInitialParams<Date>,
callback: LoadInitialCallback<Concert>) {
val items = fetchItems(params.requestedInitialKey,
params.requestedLoadSize)
callback.onResult(items)
}
override fun loadAfter(
params: LoadParams<Date>,
callback: LoadCallback<Concert>) {
val items = fetchItemsAfter(
date = params.key,
limit = params.requestedLoadSize)
callback.onResult(items)
}
}
Java
public class ConcertTimeDataSource
extends ItemKeyedDataSource<Date, Concert> {
@NonNull
@Override
public Date getKey(@NonNull Concert item) {
return item.getStartTime();
}
@Override
public void loadInitial(@NonNull LoadInitialParams<Date> params,
@NonNull LoadInitialCallback<Concert> callback) {
List<Concert> items =
fetchItems(params.key, params.requestedLoadSize);
callback.onResult(items);
}
@Override
public void loadAfter(@NonNull LoadParams<Date> params,
@NonNull LoadCallback<Concert> callback) {
List<Concert> items =
fetchItemsAfter(params.key, params.requestedLoadSize);
callback.onResult(items);
}
}
Ardından, DataSource.Factory sınıfının somut bir alt sınıfını oluşturarak bu özelleştirilmiş verileri PagedList nesnelerine yükleyebilirsiniz. Aşağıdaki kod snippet'inde, önceki kod snippet'inde tanımlanan özel veri kaynağının yeni örneklerinin nasıl oluşturulacağı gösterilmektedir:
Kotlin
class ConcertTimeDataSourceFactory :
DataSource.Factory<Date, Concert>() {
val sourceLiveData = MutableLiveData<ConcertTimeDataSource>()
var latestSource: ConcertDataSource?
override fun create(): DataSource<Date, Concert> {
latestSource = ConcertTimeDataSource()
sourceLiveData.postValue(latestSource)
return latestSource
}
}
Java
public class ConcertTimeDataSourceFactory
extends DataSource.Factory<Date, Concert> {
private MutableLiveData<ConcertTimeDataSource> sourceLiveData =
new MutableLiveData<>();
private ConcertDataSource latestSource;
@Override
public DataSource<Date, Concert> create() {
latestSource = new ConcertTimeDataSource();
sourceLiveData.postValue(latestSource);
return latestSource;
}
}
İçerik güncellemelerinin işleyiş şeklini göz önünde bulundurma
Gözlemlenebilir PagedList nesneleri oluştururken içerik güncellemelerinin işleyiş şeklini göz önünde bulundurun. Verileri doğrudan bir Room veritabanından yüklüyorsanız güncellemeler uygulamanızın kullanıcı arayüzüne otomatik olarak aktarılır.
Sayfalı ağ API'si kullanırken genellikle "yenilemek için kaydır" gibi bir kullanıcı etkileşimi, en son kullandığınız DataSource öğesini geçersiz kılmak için sinyal görevi görür. Ardından, bu veri kaynağının yeni bir örneğini istersiniz. Aşağıdaki kod snippet'i bu davranışı göstermektedir:
Kotlin
class ConcertActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// ...
concertTimeViewModel.refreshState.observe(this, Observer {
// Shows one possible way of triggering a refresh operation.
swipeRefreshLayout.isRefreshing =
it == MyNetworkState.LOADING
})
swipeRefreshLayout.setOnRefreshListener {
concertTimeViewModel.invalidateDataSource()
}
}
}
class ConcertTimeViewModel(firstConcertStartTime: Date) : ViewModel() {
val dataSourceFactory = ConcertTimeDataSourceFactory(firstConcertStartTime)
val concertList: LiveData<PagedList<Concert>> =
dataSourceFactory.toLiveData(
pageSize = 50,
fetchExecutor = myExecutor
)
fun invalidateDataSource() =
dataSourceFactory.sourceLiveData.value?.invalidate()
}
Java
public class ConcertActivity extends AppCompatActivity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
// ...
viewModel.getRefreshState()
.observe(this, new Observer<NetworkState>() {
// Shows one possible way of triggering a refresh operation.
@Override
public void onChanged(@Nullable MyNetworkState networkState) {
swipeRefreshLayout.isRefreshing =
networkState == MyNetworkState.LOADING;
}
};
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshListener() {
@Override
public void onRefresh() {
viewModel.invalidateDataSource();
}
});
}
}
public class ConcertTimeViewModel extends ViewModel {
private LiveData<PagedList<Concert>> concertList;
private DataSource<Date, Concert> mostRecentDataSource;
public ConcertTimeViewModel(Date firstConcertStartTime) {
ConcertTimeDataSourceFactory dataSourceFactory =
new ConcertTimeDataSourceFactory(firstConcertStartTime);
mostRecentDataSource = dataSourceFactory.create();
concertList = new LivePagedListBuilder<>(dataSourceFactory, 50)
.setFetchExecutor(myExecutor)
.build();
}
public void invalidateDataSource() {
mostRecentDataSource.invalidate();
}
}
Veri eşleme sağlama
Sayfalama kitaplığı, DataSource tarafından yüklenen öğelerin öğe tabanlı ve sayfa tabanlı dönüşümlerini destekler.
Aşağıdaki kod snippet'inde, konser adı ve konser tarihinin bir kombinasyonu, hem adı hem de tarihi içeren tek bir dizeyle eşlenir:
Kotlin
class ConcertViewModel : ViewModel() {
val concertDescriptions : LiveData<PagedList<String>>
init {
val concerts = database.allConcertsFactory()
.map { "${it.name} - ${it.date}" }
.toLiveData(pageSize = 50)
}
}
Java
public class ConcertViewModel extends ViewModel {
private LiveData<PagedList<String>> concertDescriptions;
public ConcertViewModel(MyDatabase database) {
DataSource.Factory<Integer, Concert> factory =
database.allConcertsFactory().map(concert ->
concert.getName() + "-" + concert.getDate());
concertDescriptions = new LivePagedListBuilder<>(
factory, /* page size */ 50).build();
}
}
Bu, öğeleri yüklendikten sonra sarmak, dönüştürmek veya hazırlamak istiyorsanız yararlı olabilir. Bu işlem, getirme yürütücüsünde yapıldığından diskten okuma veya ayrı bir veritabanını sorgulama gibi maliyetli işlemler yapabilirsiniz.
Geri bildirim gönderin
Geri bildirimlerinizi ve fikirlerinizi aşağıdaki kaynaklar aracılığıyla bizimle paylaşabilirsiniz:
- Issue Tracker

- Hataları düzeltebilmemiz için sorunları bildirin.
Ek kaynaklar
Paging Library hakkında daha fazla bilgi edinmek için aşağıdaki kaynaklara göz atın.
Örnekler
Codelab uygulamaları
Videolar
- Android Jetpack: manage infinite lists with RecyclerView and Paging (Google I/O '18)
- Android Jetpack: Paging
Sizin için önerilenler
- Not: JavaScript devre dışı olduğunda bağlantı metni gösterilir.
- Paging 3'e geçiş yapma
- Paging 2 kitaplığına genel bakış
- Sayfalı listeleri görüntüleme