android / codelab-android-paging Goto Github PK
View Code? Open in Web Editor NEWJetpack Paging codelab
License: Apache License 2.0
Jetpack Paging codelab
License: Apache License 2.0
The latest Repo with RemoteMediator implemented does not provide offline support it shows Retry button in offline.
I'm using retrofit with okhttp and migrated to AndroidX, When I make a signed app that obfuscated with proguard it crashes and gives an error,but in debug mode when proguard is not enabled it's working good. and I disabled proguard just for testing and made a signed APK it's working this way too. so I'm sure the crash is caused by Proguard. And I did some search on google they all say that I have to add proguard rules for both OKHTTP and Retrofit I did add them too but it still crashes. The error is logged from Crashlytics because I didn't enable proguard in debug mode:
PagedStorage.java line 118
androidx.paging.PagedStorage.init
Fatal Exception: java.lang.NullPointerException
Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
androidx.paging.PagedStorage.init (PagedStorage.java:118)
androidx.paging.PagedStorage.init (PagedStorage.java:131)
androidx.paging.ContiguousPagedList$1.onPageResult (ContiguousPagedList.java:81)
androidx.paging.DataSource$LoadCallbackHelper$1.run (DataSource.java:324)
android.os.Handler.handleCallback (Handler.java:790)
android.os.Handler.dispatchMessage (Handler.java:99)
android.os.Looper.loop (Looper.java:164)
android.app.ActivityThread.main (ActivityThread.java:7000)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:441)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1408)
Thread-20
java.lang.Object.wait (Object.java)
java.lang.Thread.parkFor$ (Thread.java:2137)
sun.misc.Unsafe.park (Unsafe.java:358)
java.util.concurrent.locks.LockSupport.park (LockSupport.java:190)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await (AbstractQueuedSynchronizer.java:2059)
java.util.concurrent.PriorityBlockingQueue.take (PriorityBlockingQueue.java:548)
com.android.volley.NetworkDispatcher.processRequest (NetworkDispatcher.java:104)
com.android.volley.NetworkDispatcher.run (Network
And that's my Proguard rules:
-dontwarn org.conscrypt.OpenSSLProvider
-dontwarn org.conscrypt.Conscrypt
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-keepattributes *Annotation*
-keepattributes SourceFile,LineNumberTable
-keep public class * extends java.lang.Exception
-keep class com.crashlytics.** { *; }
-dontwarn com.crashlytics.**
# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
# EnclosingMethod is required to use InnerClasses.
-keepattributes Signature, InnerClasses, EnclosingMethod
# Retain service method parameters when optimizing.
-keepclassmembers,allowshrinking,allowobfuscation interface * {
@retrofit2.http.* <methods>;
}
# Ignore annotation used for build tooling.
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
# Ignore JSR 305 annotations for embedding nullability information.
-dontwarn javax.annotation.**
# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
-dontwarn kotlin.Unit
# Top-level functions that can only be used by Kotlin.
-dontwarn retrofit2.-KotlinExtensions
# JSR 305 annotations are for embedding nullability information.
-dontwarn javax.annotation.**
# A resource is loaded with a relative path so the package of this class must be preserved.
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
-dontwarn org.codehaus.mojo.animal_sniffer.*
# OkHttp platform used only on JVM and when Conscrypt dependency is available.
-dontwarn okhttp3.internal.platform.ConscryptPlatform
-keep class com.google.android.material.** { *; }
-dontwarn com.google.android.material.**
-dontnote com.google.android.material.**
this part added after the crash but it's still useless
-dontwarn androidx.**
-keep class androidx.** { *; }
-keep interface androidx.** { *; }
-keep class androidx.paging.PagedStorage.init
And that's my gradle:
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
//noinspection GradleCompatible
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'com.google.android.material:material:1.1.0-alpha01'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha2'
implementation 'com.google.android.material:material:1.1.0-alpha01'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.0.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.vectordrawable:vectordrawable:1.0.1'
implementation 'androidx.drawerlayout:drawerlayout:1.0.0'
implementation 'com.android.volley:volley:1.1.0'
implementation 'com.google.android.gms:play-services-location:16.0.0'
implementation 'com.google.android.gms:play-services-maps:16.0.0'
implementation 'com.facebook.android:audience-network-sdk:5.1.0'
implementation 'com.facebook.android:facebook-android-sdk:4.37.0'
implementation 'com.github.KwabenBerko:OpenWeatherMap-Android-Library:v1.1.1'
implementation 'androidx.multidex:multidex:2.0.0'
implementation 'com.google.firebase:firebase-invites:16.0.5'
implementation 'com.google.firebase:firebase-core:16.0.5'
implementation 'com.google.firebase:firebase-messaging:17.3.4'
implementation 'com.crashlytics.sdk.android:crashlytics:2.9.6'
implementation 'com.firebase:firebase-jobdispatcher:0.8.5'
implementation 'com.google.firebase:firebase-analytics:16.0.5'
implementation 'com.google.firebase:firebase-dynamic-links:16.1.3'
implementation 'com.firebaseui:firebase-ui-auth:4.2.1'
implementation 'androidx.paging:paging-runtime:2.1.0-beta01'
//Rate my APP
implementation 'com.github.hotchemi:android-rate:1.0.1'
//Firebase performance
implementation 'com.google.firebase:firebase-perf:16.2.0'
implementation 'com.google.firebase:firebase-config:16.1.0'
implementation 'com.github.metalurgus:LocaleText:0.0.1.1'
implementation 'com.github.paolorotolo:appintro:v5.1.0'
/*
* Step 2: Adding ViewModel and Lifecycle
*/
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
/*
* Step 3: Adding rxJava to the app
*/
implementation 'io.reactivex.rxjava2:rxjava:2.2.2'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
implementation 'com.an.customfontview:customfont:0.1.0'
/*
* Step 4: Adding retrofit to the app
*/
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
/*
* Step 5: We would be needing an image loading library.
* So we are going to use Picasso
*/
implementation 'com.squareup.picasso:picasso:2.71828'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
implementation files('libs/YouTubeAndroidPlayerApi.jar')
}
apply plugin: 'com.google.gms.google-services'
And I have posted it to StackOverflow too:
Hello,
it's fine that you have now a Paging Library 3.0 with all the Flow stuff and other new things and so on. But I made my app using the old Paging Library with a BoundaryCallback and I am very happy with that.
I know that the software will always change but at this point, I do not want to integrate Flow into my app because it is an ExperimentalAPI which might be change in the future.
Therefore, I searched for the codelab and the Paging github page which contained the old Paging Library with PagedList.BoundaryCallback and so on.
Can you also upload that old project, please ?
Should we create a fake paging data source? Any ideas or sample to refer to?
the app doesn't work in offline mode
What I do:
override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<Songs>) {
coroutineScope.launch(Dispatchers.IO) {
val (songs, count) = getSongs(this, params.requestedLoadSize, params.requestedStartPosition)
callback.onResult(songs, 0, count)
}
}
So It's with "count" to get those infamous placeholders ....
override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<Songs>) {
//job?.cancel()
job = coroutineScope.launch(Dispatchers.IO) {
callback.onResult(mutableListOf<Songs>())
//callback.onResult(getSongs(this, params.loadSize, params.startPosition).first)
}
}
Here it would make sense to cancel the coroutine (It's a fetch on the MediaStore) and give back the part of the list loaded, but seems that it doesn't like less elements than what it expects. On the other end what's the point to fill up the list with rubbish if I want to abort the operation and visualise placeholders on the adapter with the suggested technique
if getItem(position)==null then show my beautiful placeholder
As a side note, the fact everyone says that you can't get the count from a contentProvider with "select count(*) from whatever" it's pretty annoying, but that's another story.
ah almost forgot. the stacktrace i get:
2020-06-19 10:42:29.550 23854-23854/com.shapedbyiris.consumer E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.shapedbyiris.consumer, PID: 23854
java.lang.IllegalArgumentException: page introduces incorrect tiling
at androidx.paging.PagedStorage.insertPage(PagedStorage.java:545)
at androidx.paging.PagedStorage.tryInsertPageAndTrim(PagedStorage.java:504)
at androidx.paging.TiledPagedList$1.onPageResult(TiledPagedList.java:60)
at androidx.paging.DataSource$LoadCallbackHelper$1.run(DataSource.java:324)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Edit#2:
The effect you see without cancelling is that if you scroll like crazy (and I mean real crazy) UI slows down visibly
I cloned the repo and tried to release-build it with minifyEnabled
set to true
. But can't for some problems from Proguard. See details about all I did and full error message here:
https://stackoverflow.com/questions/52283179/proguard-problem-with-official-example-of-paging-library-usage-in-google-codela
Please provide to the codelab some information about initialLoadSize of Pager class (in section 6).
It may be confusing for beginners who try making applications based on this codelab, For example, when we load data in small portions, less than default initialLoadSize, same data can be loaded multiple times (it took me some time to figure out, that that was the reason and I'm probably not the only one).
When I keep sliding the list, when the paging request network is triggered, the list automatically runs to the top
Hello!
I use library version 3.0.0-alpha01
I'm trying to implement a multi-page search using pages. However, I faced an issue that it's not possible to replace data while the previous set is processing. And it looks like there is no way to stop processing or receive callback that processing has finished
So basically my Fragment observes data from ViewModel:
lifecycleScope.launch {
@OptIn(ExperimentalCoroutinesApi::class)
viewModel.searchData.distinctUntilChanged().collectLatest {
adapter?.submitData(it)
}
}
ViewModel triggers repository:
@ExperimentalCoroutinesApi
val searchData = searchRequest.asFlow().flatMapLatest {
val selectedStatuses = selectedStatuses.value?.toList() ?: emptyList()
val search = _search.value.orEmpty()
if (search.isNotBlank() || selectedStatuses.isNotEmpty()) {
repository.search(search, selectedStatuses.value?.toList() ?: emptyList()) { statuses, total, page ->
// some converting data stuff
}
} else {
flow { emit(PagingData.empty<SearchRecyclerModel>()) }
}
}
Repository:
val pagingSource = SearchPagingSource(appDatabase, databaseDataSource, remoteDataSource, dateHelper)
fun search(search: String, statuses: List<Long>, convertToRecyclerItems: (List<Result>, Int, Int) -> List<SearchRecyclerModel>) =
Pager(
PagingConfig(PAGE_SIZE),
initialKey = SearchData(search, statuses, 0, PAGE_SIZE)
) { pagingSource.setConverter(convertToRecyclerItems) }.flow
And SearchPagingSource
class SearchPagingSource(
private val appDatabase: AppDatabase,
private val databaseDataSource: DatabaseDataSource,
private val remoteDataSource: RemoteDataSource,
private val dateHelper: DateHelper
) :
PagingSource<SearchData, SearchRecyclerModel>() {
private val dateFormat = dateHelper.serverResponseDateFormat
private var convertToRecyclerItems: ((List<Result>, Int, Int) -> List<SearchRecyclerModel>)? = null
override suspend fun load(params: LoadParams<SearchData>): LoadResult<SearchData, SearchRecyclerModel> {
return try {
val key = params.key!!
val previousKey = if (key.offset == 0) null else key.copy(offset = key.offset - 1)
var nextKey: SearchData? = null
var total: Int
// internet request
// TODO why is it UI thread?
val result = remoteDataSource.search(key.criteria, key.statusIds, key.offset, key.limit)
// Here is response parsing
// ...
//
total = result?.data?.total ?: 0
nextKey = if (total < key.limit * (key.offset + 1)) null else key.copy(offset = key.offset + 1)
LoadResult.Page(
data = convertToRecyclerItems?.invoke(result, total, key.offset) ?: emptyList(),
prevKey = previousKey,
nextKey = nextKey
)
} catch (e: IOException) {
LoadResult.Error(e)
} catch (e: HttpException) {
LoadResult.Error(e)
}
}
// Convert server response into recycler's items
fun setConverter(convertToRecyclerItems: (List<Result>, Int, Int) -> List<SearchRecyclerModel>): SearchPagingSource {
this.convertToRecyclerItems = convertToRecyclerItems
return this
}
}
data class SearchData(val criteria: String, val statusIds: List<Long>, val offset: Int, val limit: Int)
Is there a way to handle it somehow?
Room smartly runs all the queries which return LiveData
or Observable
on a background thread, then why when returning DataSource.Factory
it runs on UI thread and we have to manually run it on a background thread?
I added a swipe to delete operation which deletes the current item from database and updates the list.
However if I do multiple delete operations quickly the list gets updated and is scrolled to a random position.
When I rotate screen at the beginning of the list everything works fine, list scrolls to the right position - there where it was before rotation. When I scroll a little bit further and pass position 60~ and rotate, it always scrolls up to position 59-60. When I scroll a lot further and rotate it doesn't scroll to position 59-60 nor to last position, but to position 0.
I have the same issue in my own app which I am creating according to this codelab, when I scroll past position 144~ and rotate the screen it always scrolls up to position 143-144. and if I scroll to position before 150 and rotate the screen list scrolls to correct position. When I scroll to position like 230~ and rotate it doesn't scroll to position 143-144 nor to last position, but to position 0.
val page = when (loadType) {
LoadType.PREPEND -> {
val remoteKeys = getRemoteKeyForFirstItem(state)
if (remoteKeys == null) {
// The LoadType is PREPEND so some data was loaded before,
// so we should have been able to get remote keys
// If the remoteKeys are null, then we're an invalid state and we have a bug
throw InvalidObjectException("Remote key and the prevKey should not be null")
}
// If the previous key is null, then we can't request more data
val prevKey = remoteKeys.prevKey
if (prevKey == null) {
return MediatorResult.Success(endOfPaginationReached = true)
}
remoteKeys.prevKey
}
}
throw
statement above says "Remote key and the prevKey should not be null", but you only test on remoteKey
's nullability, not the prevKey
. Please change to correct message or behaviorif
statement tests prevKey
, in a separate value. That is in principle not necessary, please omit the prevKey
value and test on remoteKeys.prevKey
instead.RG
when i built the project i got this error:
API 'variant.getJavaCompile()' is obsolete and has been replaced with 'variant.getJavaCompileProvider()'.
It will be removed at the end of 2019.
For more information, see https://d.android.com/r/tools/task-configuration-avoidance.
To get rid of it i had to update ext.kotlin_version from 1.2.71 to 1.3.10
thanks
When use Pager with remoteMediator
, object "before" in insertSeparators
function always not null. So there is on possible to insert divider at first place.
The code in the function initSearch
shown at the end of step 9 doesn't match the instructions given nor the actual code in the solution branch https://github.com/googlecodelabs/android-paging/blob/step5-9_paging_3.0/app/src/main/java/com/example/android/codelabs/paging/ui/SearchRepositoriesActivity.kt#L104
if someone accepts this issue then i'll send a PR
Every time I pull down to load more, after the network data request is successful, the list locates the first piece of data
Really? Why project is in Kotlin language? Please, give us the choice between pure Java and Kotlin.
P.S. I came from https://codelabs.developers.google.com/codelabs/android-paging/index.html
i can't find example for Positional Data Source :(
what IN_QUALIFIER means in the code ? what it does ?
You should split this codelab in two separate codelabs, where the first is w/o Room and the second with Room. As it is now, (new) users may get confused when the two solutions are in one codelab session.
RG
at the end of codelab we finished implementing GithubRemoteMediator, but when running the app it crashes, saying in logcat "Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number." , However, RepoDatabase file is:
@Database(
entities = [Repo::class, RemoteKeys::class],
version = 1,
exportSchema = false
)
abstract class RepoDatabase : RoomDatabase() {
As you can see, I didn't increase the version or manipulate any other related database files I just walked through codelab but can't figure out why this error happens?
NETWORK_PAGE_SIZE
) and Page 5 is awaiting to be retrieved.This also happens when the user kills the app and relaunches the app to view the query results for a previously searched query. This applies for both the code samples (with or without the paging library).
Is this intended to work like this or is this a bug?
Can't see any data in list when running SearchRepositoryActivity on emulator.
Error: Unable to resolve host api.github.com
On Step 8 of the Android Paging codelab, the class file for ReposAdapter is missing. Step 8 says to modify the ReposAdapter from a ListAdapter to a PagedListAdapter, but the class file ReposAdapter itself is missing entirely.
If you experience this error in AS 3.3:
[TAG] Failed to resolve variable '${project.groupId}'
[TAG] Failed to resolve variable '${project.version}'
Follow the instructions here as solutions branch doesn't compile otherwise:
https://stackoverflow.com/a/54206976/258896
The app can be compiled and run at the end of Page 7, without swapping the ListAdapter for a PagedListAdapter (since PagedList is a List, which ListAdapter accepts).
Suggest:
At section 6 of heading Build and configure PagingData, the first point of the third paragraph misspells Kotlin as Kolin
I wrap the RecyclerView with a SwipeRefreshLayout, when first enter the list page, set the SwipeRefreshLayout to loading progress, then do the paging refresh call like this,
@ExperimentalCoroutinesApi
private fun searchHistoryData() {
swipe_container.isRefreshing = true
searchJob?.cancel()
searchJob = lifecycleScope.launch {
viewModel?.refreshGameHistory()?.collect {
swipe_container.isRefreshing = false
adapter.submitData(it)
}
}
}
Found the loading components not showing expected. profile the process via Android Studio, the RPC call executed after the adapter.submitData() calling, and it's running upon the main thread.
Since the PRC logics are in PagingSource load() suspend function. I can't decide the load function execute in which thread. my PRC function is a GRPC function, If I convert it to an async function, it will not convenient to handle the result.
In addition, the same as loading views, the footer view LoadState also been blocked.
And how should I do about this issue? If can consider adding an IO thread way to support it?
dependencies:
implementation "androidx.paging:paging-runtime:3.0.0-alpha01"
thanks!
closed
The codelab mentions SearchRepositoryActivity, but current repo contains SearchRepositoriesActivity.
https://codelabs.developers.google.com/codelabs/android-paging/index.html?index=..%2F..%2Findex#4
(Issue with the codelab text)
JNI DETECTED ERROR IN APPLICATION: input is not valid Modified UTF-8: illegal start byte 0xf0
removed emoji on no_results string resolves crashes but i wanna know why is this crashing..
PR #33 (Bumping Versions) updates the project to use android gradle plugin version 4.0.0-alpha9
. As a result, this project will only open on Android Studio version 4.0 and greater. However, the Codelab Intro pages says you only need Android Studio 3.4 or later.
The links at the bottom of page 3 of the codelab point to references of deprecated classes. They should instead point to their androidx alternatives.
Step 9 of the code lab includes the following:
Create a backing field for it, and change the type of
networkErrors
toLiveData<String>
.
The property already has a backing field, what we're doing here is creating a backing property.
Later down the page, this comes up again:
Update the
requestAndSaveData()
method to use the backing field_networkErrors
.
The first sentence on page 8 of the codelab mistakenly refers to RecyclerView
as RecycleView
.
HTTP FAILED: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x60626330: Failure in SSL library, usually a protocol error
error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version (external/openssl/ssl/s23_clnt.c:744 0x5ea7a6fd:0x00000000)
In the description, says to change some code in the method updateRepoListFromInputupdateRepoListFromInput()
, but the right name is updateRepoListFromInput()
there is using of list adapter and no paging 3.0 resoures uses any where in code
the tutorial guide to create GitPagingSource useing PagingSource
and then GitPagingData then GitRepository included with RepoSearchResponse and then guide to buid ReloadAdapter with view holder and required setup to init adapter and viewmodel data flow oberser but here nothing match the code no {
RemoteMediatorSource or dao or room where used
}
thats makes tutorial uncomplete
what if i need to perform query for each item in query result
for example
if i have Movie.class and i can get list of movies from api
and i can get the movie reviews from another api using movie id ,
if i want to display review list inside each item of movie list , how can i deal with liveData , paging and room
I would like to add a Progress Bar. How to handle it?
I'm not sure this is the right place for this issue, but I think it's where it will be clearer to explain.
I first noticed this when navigating on the app after I finished the code lab, but the stack trace below comes from the app generated with the step13-19_network_and_database
branch.
Environment:
Steps to reproduce:
I also noticed that the list will sometimes scroll to the top when updating from the database while flinging down.
And also, when the error below happens, position is 0
.
25609-25609/com.example.android.codelabs.paging E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.codelabs.paging, PID: 25609
java.lang.UnsupportedOperationException: Unknown view
at com.example.android.codelabs.paging.ui.ReposAdapter.getItemViewType(ReposAdapter.kt:42)
at androidx.recyclerview.widget.NestedAdapterWrapper.getItemViewType(NestedAdapterWrapper.java:146)
at androidx.recyclerview.widget.MergeAdapterController.getItemViewType(MergeAdapterController.java:318)
at androidx.recyclerview.widget.MergeAdapter.getItemViewType(MergeAdapter.java:174)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6283)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6216)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6212)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2314)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1631)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1591)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:668)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4215)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3926)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4484)
at android.view.View.layout(View.java:18874)
at android.view.ViewGroup.layout(ViewGroup.java:5954)
at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1915)
at android.view.View.layout(View.java:18874)
at android.view.ViewGroup.layout(ViewGroup.java:5954)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:18874)
at android.view.ViewGroup.layout(ViewGroup.java:5954)
at androidx.appcompat.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:446)
at android.view.View.layout(View.java:18874)
at android.view.ViewGroup.layout(ViewGroup.java:5954)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:18874)
at android.view.ViewGroup.layout(ViewGroup.java:5954)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
at android.view.View.layout(View.java:18874)
at android.view.ViewGroup.layout(ViewGroup.java:5954)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:935)
at android.view.View.layout(View.java:18874)
at android.view.ViewGroup.layout(ViewGroup.java:5954)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2697)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2413)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1550)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7189)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:959)
at android.view.Choreographer.doCallbacks(Choreographer.java:734)
at android.view.Choreographer.doFrame(Choreographer.java:670)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:945)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
Hi @florina-muntenescu, I have a question
In the class SearchRepositoriesViewModel.kt you are using the Transformations.map(). This method use a MediatorLiveData and this a observerForever. I have read in the android documentation that a viewmodel doesn't should observe never a liveData object. I attached a capture. My question is ¿It's good pratice use the MediatorLiveData or Transformations into ViewModel class?
Thank you very much and forgive the inconvenience.
I have followed codelabs paging 3 tutorial. I have implemented paging from network and database.
Inside GithubRemoteMediator.kt
I have set val endOfPaginationReached = page > 2 to allow maximum 2 pages for testing.
So, the problem is when I reach at the last page of list, application get crashed as remoteKeys.nextKey is null(as we have set nextKey=null for last page of list).
Also how to support caching when application is open without internet connection. currently it is showing retry button. How to show previously loaded data. I have tried to fix this by removing
// clear all tables in the database
if (loadType == LoadType.REFRESH) {
repoDatabase.remoteKeysDao().clearRemoteKeys()
repoDatabase.reposDao().clearRepos()
}
as this will now not gone delete data from database.
But still Pager does not load data available.
So how I can fix this problem?
Is there any way of detecting end of paging?
Why Pager is not returning data available in database.
if I set recyclerview's width to match parent,it will load more and more page
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.