I've just started in android development. I saw a project on github that use Retrofit to call Deezer Api and I want to implement it to my project but i ran into a trouble in the PagingSource class, here the PagingSource class :
package com.example.myapplication.data.remote.paging
import androidx.paging.PagingSource
import com.example.myapplication.data.models.ResponseData
import com.example.myapplication.data.models.album.Album
import com.example.myapplication.data.models.artist.Artist
import com.example.myapplication.data.models.tracks.Track
import com.example.myapplication.data.remote.paging.PagingDataSource
import com.example.myapplication.data.services.ServiceType
import retrofit2.HttpException
import java.io.IOException
abstract class PagingRepository(
private val query: String,
private val serviceType: ServiceType,
private val pagingDataSource: PagingDataSource
) : PagingSource\<Int, ResponseData\>() {
companion object {
private val inMemoryCache =
mutableListOf<ResponseData>() // (*) we don't care about the object type
private val queryCache = mutableListOf<String>()
}
private val startPage = 0
private val limit = 25
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, ResponseData> {
val position = params.key ?: startPage
val apiQuery = query
return try {
val oldQuery = queryCache.find {
apiQuery.equals(it, true)
}
if (oldQuery != null && position == startPage) {
val validatedResults = resultsValidatedAndSorted(apiQuery)
LoadResult.Page(
data = validatedResults,
prevKey = null,
nextKey = null
)
} else {
val response = when (serviceType) {
ServiceType.Artists -> pagingDataSource.fetchArtist(apiQuery, position * limit, limit)
ServiceType.Albums -> pagingDataSource.fetchAlbum(apiQuery, position * limit, limit)
ServiceType.Tracks -> pagingDataSource.fetchTrack(apiQuery, position * limit, limit)
}
val body = response.body()!!
val results = response.body()!!.data
queryCache.add(apiQuery)
val shelled = results.map { ResponseData(query = apiQuery, data = it) }
inMemoryCache.addAll(
shelled
)
LoadResult.Page(
data = if (position * limit <= body.total) shelled else emptyList(),
prevKey = if (position == startPage) null else position - 1,
nextKey = if (shelled.isEmpty() || position * limit > body.total) null else position + 1
)
}
} catch (exception: IOException) {
return LoadResult.Error(exception)
} catch (exception: HttpException) {
return LoadResult.Error(exception)
}
}
private fun resultsValidatedAndSorted(query: String): List<ResponseData> {
return inMemoryCache.filter {
it.query.contains(query, true)
}
}
override fun invalidate()
{
super.invalidate()
inMemoryCache.clear()
queryCache.clear()
}
}
error : 'invalidate' in 'PagingSource' is final and cannot be overridden
Here my gradle file :
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'com.google.gms.google-services'
id 'kotlin-kapt'
id 'kotlin-android'
id 'com.google.dagger.hilt.android'
id 'androidx.navigation.safeargs.kotlin'
id 'kotlin-parcelize'
}
android {
namespace 'com.example.myapplication'
compileSdk 33
defaultConfig {
applicationId "com.example.myapplication"
minSdk 33
targetSdk 33
versionCode 1
versionName "1.0"
// buildToolsVersion "30.0.2"
def secureProps = new Properties()
if (file("../secure.properties").exists()) {
file("../secure.properties")?.withInputStream { secureProps.load(it) }
}
vectorDrawables.useSupportLibrary = true
buildConfigField "String", "BASE_URL", (secureProps.getProperty("BASE_URL") ?: "")
buildConfigField "String", "SECRET", (secureProps.getProperty("SECRET") ?: "")
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
freeCompilerArgs += ["-opt-in=kotlin.RequiresOptIn"] // opt in for experimental functions
jvmTarget = '1.8'
}
buildFeatures {
viewBinding = true
dataBinding = true
}
}
dependencies {
implementation 'androidx.work:work-runtime-ktx:2.8.1'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.8.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.google.firebase:firebase-firestore-ktx:24.4.5'
implementation platform('com.google.firebase:firebase-bom:31.3.0')
implementation 'com.google.firebase:firebase-analytics-ktx:21.2.1'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
//paging
implementation 'androidx.paging:paging-common-ktx:3.1.1'
implementation 'androidx.paging:paging-runtime-ktx:3.0.0-alpha10'
//navigation
def nav_version ="2.5.3"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
//coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
// - - ViewModel
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
//glide
implementation 'com.github.bumptech.glide:glide:4.15.1'
kapt 'com.github.bumptech.glide:compiler:4.15.1'
//bottomNavigation
implementation 'com.google.android.material:material:1.8.0'
//splashscreen
implementation 'androidx.core:core-splashscreen:1.0.0'
// -- retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0'
// Lifecycle
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.1"
//implementation "androidx.lifecycle:lifecycle-runtime:2.6.1"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.1"
// HILT
def hilt_version = "2.45"
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-compiler:$hilt_version"
"androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
kapt "androidx.hilt:hilt-compiler:1.0.0"
// Timber
implementation 'com.jakewharton.timber:timber:5.0.1'
// ExoPlayer
api "com.google.android.exoplayer:exoplayer-core:2.18.5"
api "com.google.android.exoplayer:exoplayer-ui:2.18.5"
api "com.google.android.exoplayer:extension-mediasession:2.18.5"
// Firebase
implementation 'com.google.firebase:firebase-firestore:24.4.5'
// Firebase Storage KTX
implementation 'com.google.firebase:firebase-storage-ktx:20.1.0'
// Firebase Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.6.4'
implementation 'androidx.media:media:1.6.0'
implementation 'com.google.firebase:firebase-analytics-ktx:21.2.1'
// Coil Image Loading Library
implementation('io.coil-kt:coil:1.1.0')
// Subtitle supported collapsing toolbar
implementation 'com.hendraanggrian.material:collapsingtoolbarlayout-subtitle:1.1.0'
// Flow Binding
implementation 'io.github.reactivecircus.flowbinding:flowbinding-android:0.10.2'
implementation('androidx.preference:preference-ktx:1.1.1')
}
kapt {
correctErrorTypes = true
}
But when I remove the overide fun invalidate() to fun invalidate() it has another error : "'invalidate' hides member of supertype 'PagingSource' and needs 'override' modifier"
So the reason for the behaviour is that
PagingSourceis abstract. It is declared like this:From an abstract class you can not create a object.
So if you want to call
invalidateit is interpret as a final (static) method. You can not override finals. But if you don't write theoverridemodifier you hide theinvalidatefunction fromPagingSource. This is not allowed.To be precise.
fun invalidateshould have declared asabstract fun invalide()Then you must implement the function via override.But
invalidate()is declared like this and a real implementation inPagingSourceI can not solve your code because I don't know what should happen when and so on. If you just need an invalidate which you can call like this:
pagingRepository.invalidate()Then just create another function like this
pagingRepository.invalidatePaging()But again I don't know enough code and the architecture of your example. If you want to dive deep then do a google lab for paging.