HTTP 401 - Empty Recyclerview With RxJava2 And Retrofit2 In MVVM Patterns
I am pretty new to MVVM Patterns and calling API with RxJava2 and Retrofit2. I'm trying to call API from Unsplash API I have no idea what should I do, I've looked over a lot of tutorials but no solution what is happening.
Here is where I provide APIService and OkHttpClient and Retrofit:
@Provides
@Singleton
fun provideHttpLoggingInterceptor(): HttpLoggingInterceptor {
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
return interceptor
}
@Provides
@Singleton
fun provideOkHttpClient(httpLoggingInterceptor: HttpLoggingInterceptor): OkHttpClient {
val okHttpClient = OkHttpClient.Builder()
okHttpClient.apply {
if (BuildConfig.DEBUG) {
addNetworkInterceptor(StethoInterceptor())
addInterceptor(httpLoggingInterceptor)
}
}
return okHttpClient.build()
}
@Provides
@Singleton
fun provideApiService(okHttpClient: OkHttpClient): PhotoService {
val retrofit = Retrofit.Builder()
.baseUrl("https://api.unsplash.com/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.build()
return retrofit.create(PhotoService::class.java)
}
PhotoService:
@GET("photos")
fun getPhotos(@Query("page") page: Int = 1): Observable<List<Photo>>
PhotoRepository:
fun getPhotos() : PhotoService {
return photoApiService
}
ViewModel:
//=======================================================
// DISPOSABLE
//=======================================================
private var disposable: Disposable? = null
//=======================================================
// GET PHOTOS
//=======================================================
private val photoLive = MutableLiveData<List<Photo>>()
private val photoData: LiveData<List<Photo>>
get() = photoLive
@SuppressLint("LogNotTimber", "CheckResult")
fun getPhotos(): LiveData<List<Photo>> {
disposable = photoRepository.getPhotos().getPhotos()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
it -> photoLive.value = it
},
{
it -> if (it != null)
{
Log.e(TAG,Log.getStackTraceString(it))
}
})
return photoData
}
And Fragment where I set adapter:
private fun setPhotos() {
viewModel.getPhotos().observe(this, Observer<List<Photo>> {
it -> rvListPhoto.adapter = PhotosAdapter(it)
})
}
I think code from Adapter is not necessarily to put it. Because the error is from the other side but I don't know where is the problem.
And if it does matters here is the error:
retrofit2.adapter.rxjava2.HttpException: HTTP 401
at retrofit2.adapter.rxjava2.BodyObservable$BodyObserver.onNext(BodyObservable.java:54)
at retrofit2.adapter.rxjava2.BodyObservable$BodyObserver.onNext(BodyObservable.java:37)
at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:44)
at io.reactivex.Observable.subscribe(Observable.java:12005)
at retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:34)
at io.reactivex.Observable.subscribe(Observable.java:12005)
at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:571)
at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
Answer
Looking at the documentation of unsplash, seems like you need to pass client_id
with your query as a query parameter like below
https://api.unsplash.com/photos/?client_id=YOUR_ACCESS_KEY
This client_id
can be found by user authentication api at https://unsplash.com/oauth/
Check https://unsplash.com/documentation#user-authentication for more information.
Related Questions
- → should I choose reactjs+f7 or f7+vue.js?
- → Phonegap Android write to sd card
- → Local reference jquery script in nanohttpd (Android)
- → Click to navigate on mobile devices
- → How to allow api access to android or ios app only(laravel)?
- → Access the Camera and CameraRoll on Android using React Native?
- → React native change listening port
- → What is the default unit of style in React Native?
- → Google play market autocomplete icon
- → Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `ListView`
- → Using Laravel with Genymotion
- → react native using like web-based ajax function
- → react native pdf View