J'essaie d'utiliser rxJava, rxAndroid, Retrofit2 et OkHTTP3 pour télécharger un fichier à partir d'un point de terminaison d'URL. Mon code ne parvient pas à créer l'adaptateur d'appel pour un "Observable <retrofit2.Response <okhttp3.ResponseBody >>". Ces méthodes sont nouvelles pour moi, donc je crois qu'il me manque un concept important ici. Toute direction ou point est grandement apprécié.
EXCEPTION FATALE: Processus principal: com.example.khe11e.rxdownloadfile, PID: 14130 Java.lang.IllegalArgumentException: Impossible de créer l'adaptateur d'appel pour io.reactivex.Observable> pour la méthode RetrofitInterface.downloadFileByUrlRx lors de retrofit2.ServiceMethodServiceMethod .Java: 720) à retrofit2.ServiceMethod $ Builder.createCallAdapter (ServiceMethod.Java:234) à retrofit2.ServiceMethod $ Builder.build (ServiceMethod.Java:160) à retrofit2.Retrofit.loadServiceMethod (Retrofit.Java:166) .Retrofit $ 1.invoke (Retrofit.Java:145) at Java.lang.reflect.Proxy.invoke (Proxy.Java:393) at $ Proxy0.downloadFileByUrlRx (Source inconnue) sur com.example.khe11e.rxdownloadfile.MainActivity.downloadImage (MainActivity.Java:46) sur com.example.khe11e.rxdownloadfile.MainActivity $ 1.onClick (MainActivity.Java:39) sur Android.view.View.performClick (View.Java:5207) sur Android.view.View $ PerformClick .run (View.Java:21168) sur Android.os.Handler.handleCallback (Handler.Java:746) sur Android.os.Handler.dispatchMe ssage (Handler.Java:95) sur Android.os.Looper.loop (Looper.Java:148) sur Android.app.ActivityThread.main (ActivityThread.Java:5491) sur Java.lang.reflect.Method.invoke (Native Method) sur com.Android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.Java:728) sur com.Android.internal.os.ZygoteInit.main (ZygoteInit.Java:618) Causé par: Java.lang.IllegalArgumentException : Impossible de localiser l'adaptateur d'appel pour io.reactivex.Observable>. Testé: * retrofit2.adapter.rxjava.RxJavaCallAdapterFactory * retrofit2.ExecutorCallAdapterFactory à retrofit2.Retrofit.nextCallAdapter (Retrofit.Java:237) à retrofit2.Retrofit.callAdapter (Retrofit.Java:201) à retrofitModule .Java: 232) ... 16 de plus
build.gradle:
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.0.4'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
RetrofitInterface.Java:
package com.example.khe11e.rxdownloadfile;
import io.reactivex.Observable;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.http.GET;
import retrofit2.http.Streaming;
import retrofit2.http.Url;
public interface RetrofitInterface {
// Retrofit 2 GET request for rxjava
@Streaming
@GET
Observable<Response<ResponseBody>> downloadFileByUrlRx(@Url String fileUrl);
}
MainActivity.Java:
package com.example.khe11e.rxdownloadfile;
import Android.support.v7.app.AppCompatActivity;
import Android.os.Bundle;
import Android.util.Log;
import Android.view.View;
import Android.widget.Button;
import Java.io.File;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.Android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import okio.BufferedSink;
import okio.Okio;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
public class MainActivity extends AppCompatActivity {
Button downloadImgBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
downloadImgBtn = (Button) findViewById(R.id.downloadImgBtn);
downloadImgBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
downloadImage();
}
});
}
public void downloadImage(){
RetrofitInterface downloadService = createService(RetrofitInterface.class, "https://www.nasa.gov/");
downloadService.downloadFileByUrlRx("sites/default/files/iss_1.jpg")
.flatMap(processResponse())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(handleResult());
}
public <T> T createService(Class<T> serviceClass, String baseUrl){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(new OkHttpClient.Builder().build())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()).build();
return retrofit.create(serviceClass);
}
public Function<Response<ResponseBody>, Observable<File>> processResponse(){
return new Function<Response<ResponseBody>, Observable<File>>() {
@Override
public Observable<File> apply(Response<ResponseBody> responseBodyResponse) throws Exception {
return saveToDiskRx(responseBodyResponse);
}
};
}
private Observable<File> saveToDiskRx(final Response<ResponseBody> response){
return Observable.create(new ObservableOnSubscribe<File>() {
@Override
public void subscribe(ObservableEmitter<File> subscriber) throws Exception {
String header = response.headers().get("Content-Disposition");
String filename = header.replace("attachment; filename=", "");
new File("/data/data/" + getPackageName() + "/images").mkdir();
File destinationFile = new File("/data/data/" + getPackageName() + "/images/" + filename);
BufferedSink bufferedSink = Okio.buffer(Okio.sink(destinationFile));
bufferedSink.writeAll(response.body().source());
bufferedSink.close();
subscriber.onNext(destinationFile);
subscriber.onComplete();
}
});
}
private Observer<File> handleResult(){
return new Observer<File>() {
@Override
public void onSubscribe(Disposable d) {
Log.d("OnSubscribe", "OnSubscribe");
}
@Override
public void onNext(File file) {
Log.d("OnNext", "File downloaded to " + file.getAbsolutePath());
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
Log.d("Error", "Error " + e.getMessage());
}
@Override
public void onComplete() {
Log.d("OnComplete", "onCompleted");
}
};
}
}
J'ai essayé d'ajouter Call comme mentionné ici donc ça ressemble à:
Call<Observable<Response<ResponseBody>>> downloadFileByUrlRx(@Url String fileUrl);
cependant, cela provoque des problèmes avec la fonction flatMap car elle ne peut pas trouver la méthode de symbole flatMap (Function <Response <ResponseBody>, Observable <File >>).
Vous utilisez l'adaptateur RxJava 1 pour Retrofit, remplacez-le par la variante RxJava 2:
//compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
MISE À JOUR
À partir de la version Retrofit 2.2.0
il existe un adaptateur d'appel propriétaire pour RxJava2:
compile 'com.squareup.retrofit2:retrofit:2.2.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'
La version Rxjava est mise à jour vers 2.2.10
compile 'io.reactivex.rxjava2:rxandroid:2.1.1'
compile 'io.reactivex.rxjava2:rxjava:2.2.10'
compile 'com.squareup.retrofit2:retrofit:2.6.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.6.0'
La mise à niveau nécessite également au minimum Java 7 ou Android 2.3
------------------------------------------
Vous avez certainement foiré la version de votre bibliothèque.
J'utilise la dernière version de RXAndroid 2.0.1
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.1.0'
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
1) Assurez-vous que vous disposez des mêmes adaptateurs Retrofit et Retrofit-RxJava.
2) Utilisez la compilation
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
ne pas
compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0'
et utilisez RxJava2CallAdapterFactory.create()
au lieu de RxJavaCallAdapterFactory.create()
lors de la construction du retrofit.