How Observable is created in retrofit without calling it from scheduler? - android

I am working on rx-java and retrofit and I have some queries related to it.I am not able to understand that when we call below code then how Observable(Observable) is created ?
According to my understanding it should be called only during the time of scheduling and subscribing.
CryptocurrencyService cryptocurrencyService = retrofit.create(CryptocurrencyService.class);
Observable<Crypto> cryptoObservable = cryptocurrencyService.getCoinData("btc");

There is a call adapter method in Retrofit Builder which convert Call responses to corresponding one in RxJava
Retrofit.Builder()
.client(okHttpClient)
.baseUrl(baseUrl)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()
.build()

Related

How can i handle retrofit errors or get url request for to detect problems

I am trying to learn develop android applications and I'm trying to implement the latest approaches. So i use as many jetpack libraries as possible. (Dagger-Hilt, Coroutines, Retrofit etc)
Here is my question:
i have AppModule object for dependency injection.
Here is my retrofit object:
#Singleton
#Provides
fun provideConverterApi(): ConverterAPI {
return Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ConverterAPI::class.java)
}
How can i get error messages from there or for example i need to see the url i use for the request, how can i do that?
You're doing great, to add a logger for your network call use this way:
.addConverterFactory(GsonConverterFactory.create())
.addInterceptor(HttpLoggingInterceptor().apply {
level = if (DEBUG) BODY else NONE
})
.build()
Base on #Amjad Alwareh, remember to add the dependence of the HTTP logging interceptor.
implementation "com.squareup.okhttp3:logging-interceptor:${okHttpVersion}", // 3.12.1 or other version
Maybe the DEBUG should be BuildConfig.DEBUG

Unit Testing : Retrofit 2 Exception - API interfaces must not extend other interfaces

I am not extending any interface and all my interfaces are independent. While performing unit testing I am getting the following exception. During normal API calls, everything works fine.
val retrofit: Retrofit = Retrofit.Builder()
.baseUrl(url)
.client(httpBuilder.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
return retrofit.create(MyApi::class.java)
The exception is thrown at retrofit.create(..) only while performing the unit test. Is there a way to avoid this error?
This can be fixed by using dependency injection for getting Service inside the method to be tested instead of creating the instance within the method.

Where does Retrofit pull data from server?

I'm learning Coroutines of Kotlin and I'm a beginner of Retrofit.
The Code A is from the artical.
It seems that Retrofit get data from local server http://localhost/, I havn't run local web server.
Where does Retrofit get data ?
Code A
private val service: MainNetwork by lazy {
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(SkipNetworkInterceptor())
.build()
val retrofit = Retrofit.Builder()
.baseUrl("http://localhost/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
retrofit.create(MainNetwork::class.java)
}
fun getNetworkService() = service
/**
* Main network interface which will fetch a new welcome title for us
*/
interface MainNetwork {
#GET("next_title.json")
suspend fun fetchNextTitle(): String
}
Itself!
If you look at the code: .addInterceptor(SkipNetworkInterceptor()). Interceptors process every call that is made through Retrofit.
Some people use it to log data about calls for debugging. Some people use it to automatically provide authorization tokens.
In this case, it is providing fake data.
You can read about that here:
https://github.com/googlecodelabs/kotlin-coroutines/blob/master/coroutines-codelab/finished_code/src/main/java/com/example/android/kotlincoroutines/util/SkipNetworkInterceptor.kt
You should write this IP which is the equivalent of localhost in base url.
val retrofit = Retrofit.Builder()
.baseUrl("http://10.0.2.2:3000/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
But you should check your port number on localhost. After checking, you should add your port number to the part that says 3000. Replace with 3000.

Handling both Json and XML response in Retrofit - Android using addConverterFactory

I am expecting both json and xml response in my app. Retrofit 2.0 allows you to add multiple Converter Factories for such situations.
But it seems the order is of utmost importance here. Adding JacksonConverterFactory above SimpleXmlConverterFactory makes Retrofit accept only Json response and throws exception when it encounters XML and vice versa.
Below is a code snippet of how to add multiple addConverterFactory to your Retrofit Builder.
.addConverterFactory(JacksonConverterFactory.create(objectMapper))
.addConverterFactory(SimpleXmlConverterFactory.create())
<<< edit
Changed the above code to this, but still not working:
return new Retrofit.Builder()
.client(clientBuilder.build())
.baseUrl(BuildConfig.API_ENDPOINT)
.addCallAdapterFactory(unAuthorizedHandlingCallAdapterFactory)
.addCallAdapterFactory(RxErrorHandlingCallAdapterFactory.create())
.addConverterFactory(new QualifiedTypeConverterFactory(JacksonConverterFactory.create(objectMapper), SimpleXmlConverterFactory.create()))
.build();
edit2
Adding the response type was the key #GET("/") #Xml
You can combine multiple Converter Factories into a single Converter Factory, check this example from retrofit samples.

How to write a generic retrofit response and be able to log / debug it when deserialization does not work?

I struggled with this problem in the last hours and I looked for a guide.
I have an update request that I want to write in a generic way, which means that I would like to get a JSON of any kind, like a bag of property, and be able to work with it later in the application.
The problem I'm facing is that whenever I try to get it as JSON or String (and not as Model or ResponseBody) the app crashes. I think the arrest is due to decoding based on what I see.
This is the Retrofit builder.
public Retrofit getRetrofit(OkHttpClient okHttpClient) {
Retrofit retrofit = new Retrofit
.Builder()
.baseUrl("https://reqres.in/")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(MoshiConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build();
return retrofit;
}
The REST interface is super simple.
public interface IRestService {
#GET("api/users?page=2")
Observable<String> queryPage();
}
I also tried to debug this issue, and I added my logger interceptor, that obviously does not work, and I have no idea why:
public OkHttpClient getOkHttpClient(Interceptor requestInterceptor) {
// HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
// loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
HttpLoggingInterceptor loggingInterceptor =
new HttpLoggingInterceptor((msg) -> {
Log.d(HttpLoggingInterceptor.class.toString(), msg);
});
//loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
LoggingInterceptor customLoggingInterceptor = new LoggingInterceptor();
return new okhttp3.OkHttpClient.Builder()
.connectTimeout(CONNECT_TIMEOUT_IN_MS, TimeUnit.MILLISECONDS)
.addInterceptor(requestInterceptor)
.addInterceptor(loggingInterceptor)
.addInterceptor(customLoggingInterceptor)
.build();
}
Please let me know if there is anything I am doing wrong in getting the JSON out in a generic form, without a model.
And it would also be a great help if I could get some advice on how to debug this kind of problem, since the logger did not register anything in Android Studio.
Sorry if none of these questions is silly, but I've just started building my first app in Android. I have experience in many other languages.
Instead of using String for your Observable in the service(interface), use Object as the type. And when you get the data, you can always use Gson().toJson(body.toString()) to convert it to the string. Also, most probably your app is crashing for String because you don't have the correct converter factory (Scalar Factory). You can check this for the same.

Categories

Resources