Rxandroid+Retrofit学习记录

时间:2020-12-01 17:49:02

Retrofit ,rxAndroid的使用

Retrofit是一个第三方的框架,一个类型安全的http客户端实现框架,所有的接口都通过注解来实现,程序员只需要编写接口,指定编码格式以及参数,请求方式,不需要关心具体网络访问的过程。

1、 单独使用Retrofit:

使用方式:

package cp.com.rxandroiddemo;

import retrofit.Call;
import retrofit.http.GET;
import retrofit.http.Query;

/**
 * Created by chenpengfei_d on 2016/6/22.
 */
public interface NetWorkService {
    public static final String BASEURL = "http://php.weather.sina.com.cn";
    public static final String URL = "http://ip.taobao.com";
     static final String psw = "DJOYnieT8234jlsK";
    @GET("/xml.php")
    Call<Weather> getWeatherInfo(@Query(value="city",encoded=true)String city, @Query("password") String password, @Query("day")int day);
    @GET("/service/getIpInfo.php")
    Call<IpEntry> getIpPosition(@Query(value="ip",encoded=true)String ip);
}
接口通过注解实现


调用这个接口的方式:

Retrofit retrofit = new Retrofit.Builder().baseUrl(NetWorkService.BASEURL)
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create()).addConverterFactory(XmlConvertFactory.create())
                    .build();
            try {
                String s2 = URLEncoder.encode(city,"GB2312");
                Call<Weather> call = retrofit.create(NetWorkService.class).getWeatherInfo(s2,NetWorkService.psw,0);
                call.enqueue(new Callback<Weather>() {
                    @Override
                    public void onResponse(retrofit.Response<Weather> response, Retrofit retrofit) {
                        tv_result.setText(response.body().toString());
                    }

                    @Override
                    public void onFailure(Throwable t) {
                        tv_result.setText(t.toString());
                    }
                });
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

这样就是一个简单的get请求,可以看到这个请求我们是在主线程中完成,因为 call.enqueue 即可完成异步的请求。

也就是当请求完成以后都会回调到主线程中, 可以在这俩个回调方法中做操作。

(要注意的一点是:使用这个框架的话,他默认的编码格式是utf-8,可能有些接口的参数需要不同的编码格式的话那么就好先转换为相应的编码格式,然后在指定参数的地方添加类似

<span style="color:#ff0000;">@Query(value="ip",encoded=true)  这样的话就是指定不使用默认的编码格式。</span>

2、单独使用Rxandroid +rxJava:

RxAndroid 是对RxJava的拓展,RxJava是响应式编程,他是为了简化Android开发,让编程更加简洁。

使用方式:

他主要是通过观察者(observer) 以及 订阅者(subscribe)实现的。

首先的们在使用的时候通过

生产观察者对象,以及订阅者对象,然后通过观察者来监听订阅者的状态:

看代码:

 
<span style="font-family:microsoft yahei;">Observable.create(new Observable.OnSubscribe<Weather>() {
    @Override
    public void call(Subscriber<? super Weather> subscriber) {
        //1.如果已经取消订阅,则直接退出
        if(subscriber.isUnsubscribed()) return;
        try {
            //2.开网络连接请求获取天气预报,返回结果是xml格式
            String weatherXml = utils.getWeather(city);
            //3.解析xml格式,返回weather实例
            Weather weather = utils.parseWeather(weatherXml);
            //4.发布事件通知订阅者
            subscriber.onNext(weather);
            //5.事件通知完成
            subscriber.onCompleted();
        } catch(Exception e){
            //6.出现异常,通知订阅者
            subscriber.onError(e);
        }
    }
}).subscribeOn(Schedulers.newThread())    //让订阅者运行在新线程中
        .observeOn(AndroidSchedulers.mainThread())   //让观察者运行在主线程中
        .subscribe(new Subscriber<Weather>() {//这个是把订阅者跟观察者进行绑定
            @Override
            public void onCompleted() {
                //对应上面的第5点:subscriber.onCompleted();
                //这里写事件发布完成后的处理逻辑

            }

            @Override
            public void onError(Throwable e) {
                //对应上面的第6点:subscriber.onError(e);
                //这里写出现异常后的处理逻辑
                Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onNext(Weather weather) {
                //对应上面的第4点:subscriber.onNext(weather);
                //这里写获取到某一个事件通知后的处理逻辑
                if(weather != null)
                    tv_result.setText(weather.toString());
            }
        });
</span>

在观察者的call函数中执行所需要的操作,然后在订阅者的三个方法中处理结果。
Observable.create()返回的是一个泛型对象,可以转换为任意类型。  

这就是一个基本的使用。

如果要把Retrofit 与rxAndroid结合起来更加方便:

看代码的实现:

首先实现Retrofit 要进去网络请求的接口:

<span style="font-family:microsoft yahei;"> @GET("/xml.php")
    Observable<Weather> getRxWeatherInfo(@Query(value = "city" ,encoded = true)String city,@Query("password") String password, @Query("day")int day);</span>

然后在Activity中 写Rx的请求代码:

<span style="font-family:microsoft yahei;">            Retrofit retrofit = new Retrofit.Builder().baseUrl(NetWorkService.BASEURL).addConverterFactory(XmlConvertFactory.create())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create()).build();
            try {
                String s2 = URLEncoder.encode(city,"GB2312");
                NetWorkService service = retrofit.create(NetWorkService.class);
                service.getRxWeatherInfo(s2,NetWorkService.psw,0).subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<Weather>() {
                    @Override
                    public void onCompleted() {
                        tv_result.setText("onCompleted   " + tv_result.getText());
                    }

                    @Override
                    public void onError(Throwable e) {
                        tv_result.setText(e.toString());
                    }

                    @Override
                    public void onNext(Weather weather) {
                        tv_result.setText(weather.toString());
                    }
                });
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }</span>
关于RxAndroid以及Retrofit的更复杂的内容,以后慢慢记录。

在上边的代码中可以发现:

XmlConvertFactory,该类为自定义xml文件解析类,用来解析天气预报返回的xml数据。

下边再介绍下自定义

Converter.Factory类
 
<span style="font-family:microsoft yahei;">import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.ResponseBody;

import org.xml.sax.helpers.XMLReaderFactory;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import retrofit.Converter;

/**
 * Created by chenpengfei_d on 2016/6/22.
 */
public class XmlConvertFactory extends Converter.Factory{
    private   Utils utils = null;
    public static XmlConvertFactory create(){
        return create(new Utils());
    }
    public static XmlConvertFactory create(Utils utils){
        return new XmlConvertFactory(utils);
    }

    private XmlConvertFactory (Utils utils){
        if (utils != null){
            this.utils = utils;

        }else{

            throw new NullPointerException("xml == null");
        }

    }
    @Override
    public Converter<ResponseBody, ?> fromResponseBody(Type type, Annotation[] annotations) {
        return new XmlRequestBodyConverter(utils,type);
    }

    @Override public Converter<?, RequestBody> <span style="font-family: Consolas; font-size: 15pt; background-color: rgb(228, 228, 255);">toRequestBody</span><span style="font-family: Consolas; font-size: 15pt;">(Type type, Annotation[] annotations) {</span>
        return new XmlRequestBodyConverter<>( utils,type);
    }
}
</span>

从上边的代码可以看出,实现
 
Converter.Factory
然后复写他的俩个方法
 
<span style="font-family:microsoft yahei;">fromResponseBody</span>
toRequestBody
这俩个方法返回要执行解析的转换类,也是一个自定义的类
XmlRequestBodyConverter:
package cp.com.rxandroiddemo;

import com.google.gson.Gson;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;
import com.squareup.okhttp.ResponseBody;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.reflect.Type;
import java.nio.charset.Charset;

import okio.Buffer;
import retrofit.Converter;

/**
 * Created by chenpengfei_d on 2016/6/22.
 */
public class XmlRequestBodyConverter<T> implements Converter<ResponseBody, T>  {
    private final Type type;
    private Utils utils;
    private static final Charset UTF_8 = Charset.forName("UTF-8");
    XmlRequestBodyConverter(Utils utils,Type type){
        this.type = type;
        this.utils = utils;
    }
    @Override
    public T convert(ResponseBody value) throws IOException {
        String result = value.string();
        Weather weather = utils.parseWeather(result);
        return (T) weather;
    }

}

框架使用是很方便,但是还是要自己选择适合自己的框架!

Demo:http://download.csdn.net/detail/u012808234/9557774


1、Retrofit 使用post请求的时候要注意的一个点,
 
public interface NetWorkService {
 /*@GET("/testSql/index.php")
 Call<BaseMsg> login(@Query("tag") String tag, @Query("email")String email, @Query( "password")String password);
*/
   @FormUrlEncoded
   @POST("/testSql/index.php")
   Observable<BaseMsg> login(@Field("tag") String tag, @Field("email")String email, @Field("password")String password);
   @FormUrlEncoded
   @POST("/testSql/index.php")
   Observable<BaseMsg> reg (@Field("tag")String tag,@Field("name")String name,@Field("email")String email,@Field("password")String password);
}

要加
 @FormUrlEncoded,否则会报
java.lang.IllegalArgumentException: @Field parameters can only be used with form encoding. (parameter #1)