Android 使用Retrofit2问题汇总

Retrofit2引用依赖问题

    compile 'io.reactivex:rxjava:1.1.3'
    compile 'io.reactivex:rxandroid:1.1.0'
    compile 'com.squareup.retrofit2:retrofit:2.0.2'
    compile 'com.squareup.retrofit2:converter-gson:2.0.2'
    compile 'com.squareup.retrofit2:converter-scalars:2.0.2'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
    compile 'com.jakewharton:butterknife:7.0.1'
    compile 'com.squareup.okhttp3:okhttp:3.2.0'
    compile 'com.squareup.okio:okio:1.8.0'

在这里遇到一些坑,如果下面三个少一个,返回他不支持的结果时,就会崩溃,这也是上面为什么会导那么多包的原因。

private static Retrofit getRetrofit(String url) {
        return new Retrofit.Builder().baseUrl(url)
                //增加返回值为String的支持
                .addConverterFactory(ScalarsConverterFactory.create())
                //增加返回值为Gson的支持(以实体类返回)
                .addConverterFactory(GsonConverterFactory.create())
                //增加返回值为Oservable<T>的支持
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
    }

GET请求

http://wthrcdn.etouch.cn/weather_mini?city=深圳

public interface IWeather {
        @GET("/weather_mini")
        Observable<Weather> getWeather(@Query("city") String city);
}
 public static final String url_weather = "http://wthrcdn.etouch.cn";
 public static IWeather getIWeather() {
        return getRetrofit(url_weather).create(IWeather.class);
    }
HttpUtil.getIWeather().getWeather("深圳")
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Action1<Weather>() {
                            @Override
                            public void call(Weather weather) {
                                tv.setText(weather.getData().getGanmao());
                            }
                        });

Post请求

根据后台,Multipart或FormUrlEncoded,如果不知道最好两种都试一下,我在这里也是遇了大坑,如果方式错了,根本就post不上去。。

Multipart

http://122.114.38.95:8857 (这个是用的自己的服务器,后面的人看到这篇博客可能这个api就用不了了)
参数是 action , 如果action=banner就可以返回正确结果否则错误结果

 @Multipart @POST("/") Observable<String> getBanner(@Part("action") String action);
public static final String url_bannertest = "http://122.114.38.95:8857";
public static IBannerTest getBanner() {
        return getRetrofit(url_bannertest).create(IBannerTest.class);
    }
HttpUtil.getBanner().getBanner("banner")
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Action1<String>() {
                            @Override
                            public void call(String s) {
                                tv.setText(s);
                            }
                        });

post上传图片

在这里是用了image++的接口。
http://apicn.imageplusplus.com/analyze?
参数:api_key,api_secret, img

@Multipart
    @POST("/analyze")
    Observable<String> upLoadImage( @Part("api_key") String api_key, @Part ("api_secret") String api_secret,@Part MultipartBody.Part file );
public static final String imagepp_url = "http://apicn.imageplusplus.com";
 public static IImagePP getIImagePP() {
        return getRetrofit(imagepp_url).create(IImagePP.class);
    }

 public static MultipartBody.Part postFileParams(String key, File file) {
        RequestBody fileBody = RequestBody.create(MediaType.parse("image/*"), file);
        return MultipartBody.Part.createFormData(key, file.getName(), fileBody);
    }
File file = new File(Environment.getExternalStorageDirectory()+"/123.png");
                HttpUtil.getIImagePP().upLoadImage("c1a2b3ab56a2f218aed9b2ab3c16ce88","be8318b73cef1c2bcafb6c8a77922436",HttpUtil.postFileParams("img", file))
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Action1<String>() {
                            @Override
                            public void call(String s) {
                                tv.setText(s);
                            }
                        });

这里用到了okhttp的特性,这也是为什么要导入okhttp的原因。

private static Retrofit getRetrofit(String url) {
        return new Retrofit.Builder().baseUrl(url)
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
    }

上面说到了Retrofit加入了3句。
ScalarsConverterFactory是支持返回String类型
GsonConverterFactory是支持返回实体类。
RxJavaCallAdapterFactory是支持返回rxJava的Observable。

上面的例子Get请求用到了GsonConverterFactory和RxJavaCallAdapterFactory。
Post用到了ScalarsConverterFactory和RxJavaCallAdapterFactory
少一个都会蹦,所以大家用retrofit需要注意这一点。

线程(Scheduler)

Scheduler是RxJava的线程调度器,可以指定代码执行的线程。RxJava内置了几种线程:

AndroidSchedulers.mainThread() 主线程

Schedulers.immediate() 当前线程,即默认Scheduler

Schedulers.newThread() 启用新线程

Schedulers.io() IO线程,内部是一个数量无上限的线程池,可以进行文件、数据库和网络操作。

Schedulers.computation() CPU计算用的线程,内部是一个数目固定为CPU核数的线程池,适合于CPU密集型计算,不能操作文件、数据库和网络。

在实际项目中,Schedulers选择 newThread 还是io呢?

一般的网络请求应该使用io,因为io使用了无限的线程池,而newThread没有线程池维护

参考:http://blog.csdn.net/jdsjlzx/article/details/51497237

onNext方法出现异常

Observer的onNext方法被调用后,它的onError方法也紧跟着被调用了……我的第一反应是RxJava的Bug?……

当然不是了

 @Override
    public void onNext(T args) {
        try {
            if (!done) {
                actual.onNext(args);
            }
        } catch (Throwable e) {
            // we handle here instead of another method so we don't add stacks to the frame
            // which can prevent it from being able to handle StackOverflow
            Exceptions.throwIfFatal(e);
            // handle errors if the onNext implementation fails, not just if the Observable fails
            onError(e);
        }
    }

// handle errors if the onNext implementation fails, not just if the Observable fails
当onNext里我们的函数发生异常时,onError会被调用

@Path与@Query

@GET("{username}") Call<User> getUser(@Path("username") String username);
@POST("users") Call<List<User>> getUsersBySort(@Query("sort") String sort);

通过代码一比较就知道区别了。

你可能感兴趣的:(Retrofit2)