Coder Social home page Coder Social logo

codelab-android-paging's People

Contributors

florina-muntenescu avatar keyboardsurfer avatar tunjid avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

codelab-android-paging's Issues

androidx.paging.PagedStorage.init is giving error when proguard is enabled

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:

Where I can find the old way of using the Paging Library ?

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 ?

PositionalDataSource cancelling fetch for loadRange(params: LoadRangeParams, callback: LoadRangeCallback<Songs>) crashes

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

initialLoadSize issue

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).

paging some error

When I keep sliding the list, when the paging request network is triggered, the list automatically runs to the top

Collecting from multiple PagingData concurrently is an illegal operation

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?

Not Bug, rather a question

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?

List scrolls to random position after screen rotation

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.

Section 18: PREPEND Section, some unclear issues

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
    }
  }
  1. The 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 behavior
  2. The latter if 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

List divider at start of list

When use Pager with remoteMediator, object "before" in insertSeparators function always not null. So there is on possible to insert divider at first place.

load more bug

Every time I pull down to load more, after the network data request is successful, the list locates the first piece of data

Split this tutorial in with and without Room.

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

App crashes with offline mode on Android API 29, Android Studio 4.2 canary 1

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?

Multiple Network requests issued

  • Lets say user is viewing the repositories for the search "Android", and the scrolled to about 200 items in the result.
  • In other words, 200 items are now loaded into the RecyclerView's Adapter. The Last Page index at this stage will be 4 (for 50 items requested per page from the network - NETWORK_PAGE_SIZE) and Page 5 is awaiting to be retrieved.
  • The User now rotates the device to Landscape orientation.
  • Now the user scrolls to the end. At this stage, network request will be triggered but it will start requesting from page 1, until the page to be shown is requested. In the stated example, it will poll from page index 1 to page index 5, instead of just the page index 5.

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?

Missing ReposAdapter Class!

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.

Our app finally compiles! on Page 8

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:

  • remove "Our app finally compiles!" on Page 8, or moving it before the instruction to change to PagedListAdapter.
  • Add note on what the PagedListAdapter provides over a ListAdapter; i.e. is there any benefit (or detrimental) to the work up to this point if we didn't swap the ListAdapter for PagedListAdapter?

Typo at section 6

At section 6 of heading Build and configure PagingData, the first point of the third paragraph misspells Kotlin as Kolin

Paging3 uses the MainThread RPC calling that block the ui thread

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!

Crash on lollipop

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..

Android Studio 4.0 is required to run this codelab now...

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.

Terminology error in step 9

Step 9 of the code lab includes the following:

Create a backing field for it, and change the type of networkErrors to LiveData<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.

Typo on Page 8

The first sentence on page 8 of the codelab mistakenly refers to RecyclerView as RecycleView.

HTTP FAILED

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)

Wrong method name in Step 9

In the description, says to change some code in the method updateRepoListFromInputupdateRepoListFromInput(), but the right name is updateRepoListFromInput()

Code completey different from android codelab tutorial

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

nested scroll view not work

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

Final app (network + database) crashes when scrolling up and down (a lot)

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:

  • Android Studio 4.1.0-alpha10, AGP 4.1.0-beta01, Gradle 6.5-rc-1
  • Device: Samsung Galaxy S8, Android 7.0 (API 24)
  • Emulator: Pixel 3a, Android 10 (API 29)

Steps to reproduce:

  • Run app
  • Fling the list down many times
  • If still not happening, fling up a few times and then back down.

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)

Question about Architecture

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?

image

Thank you very much and forgive the inconvenience.

Application get crashed when reached at end.

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.