Sayfa 2 kitaplığına genel bakış Android Jetpack'in bir parçasıdır.
Sayfalama Kitaplığı, aynı anda küçük veri parçalarını yüklemenize ve görüntülemenize yardımcı olur. İsteğe bağlı verilerin bir kısmını yüklemek, ağ bant genişliği ve sistem kaynaklarının kullanımını azaltır.
Bu kılavuzda, kütüphane hakkında çeşitli kavramsal örnekler ve kitaplığın nasıl çalıştığına dair genel bir bakış sunulmaktadır. Bu kitaplığın nasıl çalıştığına dair eksiksiz örnekleri görmek için codelab'i ve ek kaynaklar bölümündeki örnekleri deneyin.
Kurulum
Sayfalama bileşenlerini Android uygulamanıza aktarmak için aşağıdaki bağımlılıkları uygulamanızın build.gradle
dosyasına ekleyin:
Eski
dependencies { def paging_version = "2.1.2" implementation "androidx.paging:paging-runtime:$paging_version" // For Kotlin use paging-runtime-ktx // alternatively - without Android dependencies for testing testImplementation "androidx.paging:paging-common:$paging_version" // For Kotlin use paging-common-ktx // optional - RxJava support implementation "androidx.paging:paging-rxjava2:$paging_version" // For Kotlin use paging-rxjava2-ktx }
Kotlin
dependencies { val paging_version = "2.1.2" implementation("androidx.paging:paging-runtime:$paging_version") // For Kotlin use paging-runtime-ktx // alternatively - without Android dependencies for testing testImplementation("androidx.paging:paging-common:$paging_version") // For Kotlin use paging-common-ktx // optional - RxJava support implementation("androidx.paging:paging-rxjava2:$paging_version") // For Kotlin use paging-rxjava2-ktx }
Kütüphane mimarisi
Bu bölümde sayfa oluşturma kitaplığının ana bileşenleri açıklanır ve gösterilmektedir.
Sayfalı Liste
Sayfalandırma Kitaplığı'nın temel bileşeni, uygulama verilerinizin veya sayfaların parçalarını yükleyen PagedList
sınıfıdır. Daha fazla veri gerektikçe bu veriler mevcut PagedList
nesnesine sayfalandırılır. Yüklenen herhangi bir veri değişirse LiveData
veya RxJava2 tabanlı bir nesneden gözlemlenebilir veri sahibine yeni bir PagedList
örneği gönderilir. PagedList
nesneleri oluşturulduğunda uygulamanızın kullanıcı arayüzü, bu nesneleri gösterirken kullanıcı arayüzü denetleyicilerinizin yaşam döngüsüne de uygun hareket eder.
Aşağıdaki kod snippet'i, uygulamanızın görüntüleme modelini, PagedList
nesnelerinden oluşan bir LiveData
tutucuyu kullanarak veri yüklemek ve sunmak için nasıl yapılandırabileceğinizi gösterir:
Kotlin
class ConcertViewModel(concertDao: ConcertDao) : ViewModel() { val concertList: LiveData<PagedList<Concert>> = concertDao.concertsByDate().toLiveData(pageSize = 50) }
Java
public class ConcertViewModel extends ViewModel { private ConcertDao concertDao; public final LiveData<PagedList<Concert>> concertList; // Creates a PagedList object with 50 items per page. public ConcertViewModel(ConcertDao concertDao) { this.concertDao = concertDao; concertList = new LivePagedListBuilder<>( concertDao.concertsByDate(), 50).build(); } }
Veri
Her PagedList
örneği, karşılık gelen DataSource
nesnesinden uygulama verilerinizin güncel bir anlık görüntüsünü yükler. Uygulamanızın arka ucundan veya veritabanından PagedList
nesnesine veri akışı olur.
Aşağıdaki örnekte, uygulamanızın verilerini düzenlemek için Oda kalıcı kitaplığı kullanılmıştır ancak verilerinizi başka bir yöntemle depolamak istiyorsanız kendi veri kaynağı fabrikanızı da sağlayabilirsiniz.
Kotlin
@Dao interface ConcertDao { // The Int type parameter tells Room to use a PositionalDataSource object. @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. @Query("SELECT * FROM concerts ORDER BY date DESC") DataSource.Factory<Integer, Concert> concertsByDate(); }
PagedList
nesnelerine nasıl veri yükleyebileceğiniz hakkında daha fazla bilgi edinmek için Sayfa verilen verileri yükleme ile ilgili kılavuza bakın.
Kullanıcı Arayüzü
PagedList
sınıfı, öğeleri RecyclerView
klasörüne yüklemek için bir PagedListAdapter
ile birlikte çalışır. Bu sınıflar, yüklenen içeriği getirmek ve görüntülemek, görüntü dışı içeriği önceden getirmek ve içerik değişikliklerini canlandırmak için birlikte çalışır.
Daha fazla bilgi edinmek için Sayfalı listeleri görüntüleme kılavuzuna bakın.
Farklı veri mimarilerini destekleme
Sayfalama Kitaplığı aşağıdaki veri mimarilerini destekler:
- Yalnızca arka uç sunucusundan sunulur.
- Yalnızca cihaz üzerindeki bir veritabanında depolanır.
- Cihaz üzerindeki veritabanını önbellek olarak kullanan diğer kaynakların kombinasyonu.
Şekil 1'de bu mimari senaryolarının her birinde veri akışı gösterilmektedir. Yalnızca ağ veya yalnızca veritabanı çözümü durumunda veriler doğrudan uygulamanızın kullanıcı arayüzü modeline aktarılır. Birleşik bir yaklaşım kullanıyorsanız veriler arka uç sunucunuzdan cihaz üzerindeki bir veritabanına ve daha sonra uygulamanızın kullanıcı arayüzü modeline akar. Bazen, her veri akışının uç noktasında yüklenecek veri kalmaz. Bu noktada veri sağlayan bileşenden daha fazla veri istenir. Örneğin, bir cihaz üzerindeki veritabanında veri kalmadığında sunucudan daha fazla veri ister.
![Veri akışı diyagramları](https://developer.android.google.cn/static/topic/libraries/architecture/images/paging-library-data-flow.png?authuser=9&hl=tr)
Bu bölümün geri kalanında, her bir veri akışı kullanım alanının yapılandırılmasına ilişkin öneriler verilmiştir.
Yalnızca ağ
Bir arka uç sunucusundan alınan verileri görüntülemek için Retrofit API'nin eşzamanlı sürümünü kullanarak bilgileri kendi özel DataSource
nesnenize yükleyin.
Yalnızca veritabanı
Tercihen Oda kalıcı kitaplığını kullanarak yerel depolama alanını gözlemlemek için RecyclerView
cihazınızı ayarlayın. Böylece, uygulamanızın veritabanına her veri eklendiğinde veya mevcut veritabanında her değişiklik yapıldığında, söz konusu değişiklikler bu verileri gösteren RecyclerView
öğesine otomatik olarak yansıtılır.
Ağ ve veritabanı
Veritabanını gözlemlemeye başladıktan sonra, PagedList.BoundaryCallback
kullanarak veritabanında veri kalmadığında dinleme yapabilirsiniz.
Daha sonra ağınızdan daha fazla öğe getirebilir ve bunları veritabanına ekleyebilirsiniz. Kullanıcı arayüzünüz veritabanını gözlemliyorsa tek yapmanız gereken budur.
Ağ hatalarını işleme
Çağrı Kitaplığı'nı kullanarak görüntülemekte olduğunuz verileri getirmek veya sayfalamak için bir ağ kullanırken, birçok bağlantı kesintili veya kesintili olduğundan, ağı her zaman "kullanılabilir" veya "kullanılamıyor" şeklinde değerlendirmemek önemlidir:
- Belirli bir sunucu, ağ isteğine yanıt vermeyebilir.
- Cihaz yavaş veya zayıf bir ağa bağlı olabilir.
Bunun yerine, uygulamanız hata olup olmadığını kontrol etmeli ve ağın kullanılamadığı durumlarda mümkün olduğunca sorunsuz bir şekilde kurtarma yapmalıdır. Örneğin, kullanıcılara veri yenileme adımının işe yaramazsa seçmeleri için bir "yeniden dene" düğmesi sağlayabilirsiniz. Veri sayfalama adımında bir hata oluşursa sayfalama isteklerini otomatik olarak yeniden denemek en iyisidir.
Mevcut uygulamanızı güncelleyin
Uygulamanız zaten bir veritabanından veya arka uç kaynağından veri kullanıyorsa Sayfalama Kitaplığı'nın sağladığı işlevlere doğrudan yükseltme yapmak mümkündür. Bu bölümde, ortak bir mevcut tasarıma sahip bir uygulamanın nasıl yeni sürüme geçirileceği gösterilmektedir.
Özel sayfalama çözümleri
Uygulamanızın veri kaynağından küçük veri alt kümelerini yüklemek için özel işlev kullanıyorsanız bu mantığı PagedList
sınıfındaki mantıkla değiştirebilirsiniz. PagedList
örnekleri, yaygın veri kaynaklarına yerleşik bağlantılar sunar. Bu örnekler, uygulamanızın kullanıcı arayüzüne ekleyebileceğiniz RecyclerView
nesneleri için de bağdaştırıcılar sağlar.
Sayfalar yerine listeler kullanılarak yüklenen veriler
Kullanıcı arayüzünüzün bağdaştırıcısı için yedekleme veri yapısı olarak bellek içi liste kullanıyorsanız listedeki öğelerin sayısı fazlalaşabiliyorsa PagedList
sınıfı kullanarak veri güncellemelerini gözlemlemeyi düşünün. PagedList
örnekleri, veri güncellemelerini uygulamanızın kullanıcı arayüzüne iletmek için LiveData<PagedList>
veya Observable<List>
kullanarak yükleme sürelerini ve bellek kullanımını en aza indirir. Daha da iyisi, uygulamanızda bir List
nesnesini PagedList
nesnesiyle değiştirmek, uygulamanızın kullanıcı arayüzü yapısında veya veri güncelleme mantığında herhangi bir değişiklik gerektirmez.
CursorAdapter'ı kullanarak bir veri imlecini liste görünümüyle ilişkilendirme
Uygulamanız, Cursor
aracındaki verileri bir ListView
ile ilişkilendirmek için CursorAdapter
kullanabilir. Bu durumda, genellikle uygulamanızın liste kullanıcı arayüzü kapsayıcısı olarak bir ListView
öğesinden RecyclerView
öğesine geçmeniz ve ardından Cursor
örneklerinin SQLite veritabanına erişip erişemediğine bağlı olarak Cursor
bileşenini Room veyaPositionalDataSource
ile değiştirmeniz gerekir.
Bazı durumlarda (örneğin, Spinner
örnekleriyle çalışırken yalnızca adaptörün kendisini sağlarsınız). Daha sonra bir kitaplık, bu bağdaştırıcıya yüklenen verileri alır ve verileri sizin için görüntüler. Bu tür durumlarda, bağdaştırıcınızın veri türünü LiveData<PagedList>
olarak değiştirin ve ardından bir kitaplık sınıfının kullanıcı arayüzünde bu öğeleri genişletmesini denemeden önce bu listeyi bir ArrayAdapter
nesnesinin içine alın.
AsyncListUtil kullanarak içeriği eşzamansız olarak yükleme
Bilgi gruplarını eşzamansız olarak yüklemek ve görüntülemek için AsyncListUtil
nesnelerini kullanıyorsanız Sayfalandırma Kitaplığı, verileri daha kolay yüklemenize olanak tanır:
- Verilerinizin konum odaklı olması gerekmez. Sayfalama Kitaplığı, ağın sağladığı anahtarları kullanarak verileri doğrudan arka ucunuzdan yüklemenize olanak tanır.
- Verileriniz sayılamayacak kadar büyük olabilir. Sayfalama Kitaplığı'nı kullanarak, hiç veri kalmayana kadar sayfalara veri yükleyebilirsiniz.
- Verilerinizi daha kolay gözlemleyebilirsiniz. Sayfalama kitaplığı, uygulamanızın ViewModelinin gözlemlenebilir bir veri yapısında tuttuğu verilerinizi sunabilir.
Veritabanı örnekleri
Aşağıdaki kod snippet'leri, tüm parçaların birlikte çalışmasını sağlamanın birkaç olası yolunu göstermektedir.
LiveData kullanarak sayfalandırılmış verileri gözlemleme
Aşağıdaki kod snippet'i, tüm parçaların birlikte çalışmasını gösterir. Konser etkinlikleri veritabanına eklendiğinde, kaldırıldığında veya veritabanında değiştirildikçe RecyclerView
'daki içerik de otomatik ve etkili bir şekilde güncellenir:
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> } class ConcertViewModel(concertDao: ConcertDao) : ViewModel() { val concertList: LiveData<PagedList<Concert>> = concertDao.concertsByDate().toLiveData(pageSize = 50) } class ConcertActivity : AppCompatActivity() { public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Use the 'by viewModels()' Kotlin property delegate // from the activity-ktx artifact val viewModel: ConcertViewModel by viewModels() val recyclerView = findViewById(R.id.concert_list) val adapter = ConcertAdapter() viewModel.concertList.observe(this, PagedList(adapter::submitList)) recyclerView.setAdapter(adapter) } } class ConcertAdapter() : PagedListAdapter<Concert, ConcertViewHolder>(DIFF_CALLBACK) { 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 = object : DiffUtil.ItemCallback<Concert>() { // Concert details may have changed if reloaded from the database, // but ID is fixed. override fun areItemsTheSame(oldConcert: Concert, newConcert: Concert) = oldConcert.id == newConcert.id override fun areContentsTheSame(oldConcert: Concert, newConcert: Concert) = oldConcert == newConcert } } }
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(); } public class ConcertViewModel extends ViewModel { private ConcertDao concertDao; public final LiveData<PagedList<Concert>> concertList; public ConcertViewModel(ConcertDao concertDao) { this.concertDao = concertDao; concertList = new LivePagedListBuilder<>( concertDao.concertsByDate(), /* page size */ 50).build(); } } public class ConcertActivity extends AppCompatActivity { @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); ConcertViewModel viewModel = new ViewModelProvider(this).get(ConcertViewModel.class); RecyclerView recyclerView = findViewById(R.id.concert_list); ConcertAdapter adapter = new ConcertAdapter(); viewModel.concertList.observe(this, adapter::submitList); recyclerView.setAdapter(adapter); } } 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); if (concert != null) { holder.bindTo(concert); } else { // Null defines a placeholder item - PagedListAdapter automatically // invalidates this row when the actual object is loaded from the // database. holder.clear(); } } private static DiffUtil.ItemCallback<Concert> DIFF_CALLBACK = new DiffUtil.ItemCallback<Concert>() { // Concert details may have changed if reloaded from the database, // but ID is fixed. @Override public boolean areItemsTheSame(Concert oldConcert, Concert newConcert) { return oldConcert.getId() == newConcert.getId(); } @Override public boolean areContentsTheSame(Concert oldConcert, Concert newConcert) { return oldConcert.equals(newConcert); } }; }
RxJava2 kullanarak sayfalandırılmış verileri gözlemleme
LiveData
yerine RxJava2'yi kullanmayı tercih ederseniz bunun yerine bir Observable
veya Flowable
nesnesi oluşturabilirsiniz:
Kotlin
class ConcertViewModel(concertDao: ConcertDao) : ViewModel() { val concertList: Observable<PagedList<Concert>> = concertDao.concertsByDate().toObservable(pageSize = 50) }
Java
public class ConcertViewModel extends ViewModel { private ConcertDao concertDao; public final Observable<PagedList<Concert>> concertList; public ConcertViewModel(ConcertDao concertDao) { this.concertDao = concertDao; concertList = new RxPagedListBuilder<>( concertDao.concertsByDate(), /* page size */ 50) .buildObservable(); } }
Daha sonra aşağıdaki snippet'teki kodu kullanarak verileri gözlemlemeyi başlatabilir ve durdurabilirsiniz:
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() private val disposable = CompositeDisposable() public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val recyclerView = findViewById(R.id.concert_list) recyclerView.setAdapter(adapter) } override fun onStart() { super.onStart() disposable.add(viewModel.concertList .subscribe(adapter::submitList))) } override fun onStop() { super.onStop() disposable.clear() } }
Java
public class ConcertActivity extends AppCompatActivity { private ConcertAdapter adapter = new ConcertAdapter(); private ConcertViewModel viewModel; private CompositeDisposable disposable = new CompositeDisposable(); @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); RecyclerView recyclerView = findViewById(R.id.concert_list); viewModel = new ViewModelProvider(this).get(ConcertViewModel.class); recyclerView.setAdapter(adapter); } @Override protected void onStart() { super.onStart(); disposable.add(viewModel.concertList .subscribe(adapter.submitList(flowableList) )); } @Override protected void onStop() { super.onStop(); disposable.clear(); } }
ConcertDao
ve ConcertAdapter
kodu, LiveData
tabanlı çözümlerle RxJava2 tabanlı çözümlerin kodu aynıdır.
Geri bildirim gönderme
Aşağıdaki kaynakları kullanarak geri bildirimlerinizi ve fikirlerinizi bizimle paylaşabilirsiniz:
- Sorun izleyici
- Hataları düzeltebilmemiz için sorunları bildirin.
Ek kaynaklar
Sayfalama Kitaplığı hakkında daha fazla bilgi için aşağıdaki kaynaklara bakın.
Sana Özel
Codelab uygulamaları
Videolar
- Android Jetpack: RecyclerView ve Paging ile sonsuz listeleri yönetin (Google I/O '18)
- Android Jetpack: Çağrı
Sizin için önerilenler
- Not: Bağlantı metni JavaScript kapalıyken gösterilir
- 3. Sayfaya Geçiş
- Sayfalı listeleri görüntüle
- Sayfalandırılmış verileri toplama