0

I was making a call using Retrofit before I tried to use Paging 3 library and I was getting code 200 and all working good.Then, I tried to implement Paging 3 libray and using Retrofit with it and I don't know why, I'm getting error 401. I tried some Paging 3 sample and all of this samples don't use headers in the API call, is there any problem to add headers in API call using Paging 3? I'm not sure if there is a problem with the use of headers or I'm just doing something wrong implementing Paging 3 library.

My code:

Service:

interface APICalls{
    @GET(MYAPIURL)
    suspend fun getData(
        @Header("Auth") auth : String,
        @Query("pageSize") pageSize:Int
    ):Response<ResponseData>
}

Models:

data class ResponseData(
    @SerializedName("listData") val listData:MutableList<DataAPI>,
    @SerializedName("pageSize") val pageSize : Int
):Serializable

data class DataAPI(
    @SerializedName("id") val id:Int,
    @SerializedName("data")val data: String
): Serializable

Result wrapper:

class Result<out T:Any>{
    data class Success<T:Any>(val value: T): Result<T>()
    data class Failure(val message:String, val errorCode:Int?):Result<Nothing>()
}

PagingSource:

val responseData = mutableListOf<DataAPI>()
class DataAPIPagingSource(private val token:String,private val apiCalls:APICalls) : PagingSource<Int,DataAPI>{
    
    override fun getRefreshKey(...):Int?{
        return null
    }
    override suspend fun load(params : LoadParams<Int>):LoadResult<Int,DataAPI>{
        return try{
            val currentPage = params.key ?: 1
            val response = apiCalls.getData(token)
            response.body()?.let{
                Result.Success(it)  
            }?: run{
                Result.Failure(response.message(),response.code())
            }
            val data = response.body()?.listData ?: emptyList()
            responseData.addAll(data)
            LoadResult.Page(responseData,if(currentPage ==1) null else -1),currentPage.plus(1)
            

        }catch(e:Exception){
            LoadResult.Error(e)
        }   
    }
}

ViewModel:

class DataViewModel(private val apiCalls:APICalls): ViewModel {

    //I get this token in shared preference
    val token = .....

    val mydata = getDataList()
        .map{pagingData -> pagingData.map{DataModel.DataItem(it)}}

    private fun getDataList(){
        return Pager(PagingConfig(25)){
            DataAPIPagingSource(token,apiCalls)
        }.flow.cachedIn(viewModelScope)
    }
}

sealed class DataModel{
    data class DataItem(val dataitem: DataAPI) : DataModel()
}

private val DataModel.DataItem.identificator : Int
    get() = this.dataItem.id

Fragment:

class MyFragment : Fragment(){
    private val myAdapter : DataAdapter by lazy{
        DataAdapter()
    }
    private val viewModelFactory : ViewModelFactory by inject()
    private val dataViewModel : DataViewModel by navGraphViewModels(R.id.nav_graph){viewModelFactory}


    override fun onViewCreated(...){
        super.onViewCreated(...)
        binding.myRecyclerView.apply{
            adapter = myAdapter
            layoutManager = StaggeredGridLayoutManager(1,StaggeredGridLayoutManager.VERTICAL)
            setHasFixedSize(true)
        }
        
        lyfecycleScope.launch{
            dataViewModel.mydata.collect{myAdapter.submitData(it)}
        }
    }
}

Adapter:

class DataAdapter : PagingDataAdapter<DataModel,RecyclerView.ViewHolder>(DataModelComparator){

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position:Int){

        val dataModel : DataModel? = getItem(position)
        dataModel.let{
            when(dataModel){
                is DataModel.DataItem ->{
                    val viewHolder = holder as DataItemViewHolder
                    viewHolder.binding.textview1.text = dataModel.dataitem.data
                }
            }
        }
    }
    override fun getItemViewType(position:Int):Int{
        return when(getItem(position)){
            is DataModel.DataItem -> R.layout.item_data
            null -> throw UnsupportedOperationException("Unknown view")
        }
    }

    override fun onCreateViewHolder(...){
        return when(viewType){
            R.layout.item_data ->{
                DataItemViewHolder(ItemDataBinding.inflate(...))
            }
        }
    }
    
    class DataItemViewHolder(val binding: DataItemBinding): RecyclerView.ViewHolder(binding.root)

    companion object {
         val DataModelComparator = object : DiffUtil.ItemCallback<DataModel>() {
            override fun areItemsTheSame(oldItem: Movie, newItem: Movie): Boolean {
                 return oldItem.dataitem.id == newItem.dataitem.id
            }

            override fun areContentsTheSame(oldItem: DataModel, newItem: DataModel): Boolean {
                return oldItem == newItem
            }
        }
    }
}
RaceyT
  • 135
  • 1
  • 8
  • `401` is unauthorized which means you don't have access to that API. please check if you have to pass any token or so in the API. I don't think it's related to Retrofit. – daksh bhardwaj Aug 08 '22 at 07:18

1 Answers1

0

I don't think the 401 error is related to paging 3.

You can use OkHttp Interceptor - authenticator.

Gist

Arda Kazancı
  • 8,341
  • 4
  • 28
  • 50