最近看了retrofit框架,比较新的网络访问请求框架,很多项目都涉及到,所以学习了一下,做个总结。
第一讲 retrofit2.0单独使用
1、导入依赖jar包(也可能是library,反正studio会自动下载)
compile ‘io.reactivex:rxandroid:1.1.0’
compile ‘io.reactivex:rxjava:1.1.0’
compile ‘com.squareup.retrofit:retrofit:2.0.0-beta2’
compile ‘com.squareup.retrofit:converter-gson:2.0.0-beta2’
compile ‘com.squareup.retrofit:adapter-rxjava:2.0.0-beta2’
2、创建访问网络接口(其实就是构造utl)
public interface GitHubApi {
@GET(“repos/{owner}/{repo}/contributors”)
Call get(@Path(“owner”) String owner, @Path(“repo”) String repo);
}
这里面使用了注解代码,大家可以自行百度学习一下。
主要有:
@path
@GET
@POST
@QUERY
@QUERYMAP
简单来说,就是构造网络访问的url
这里面
Call 方法(参数);
Call 方法();
T:返回的数据类型
这个是固定模板。
当然,
如果结合使用了rxjava,模板也可以是:
Observable 方法(XXX);
3、使用Call.enqueue访问网络
访问网络耗时操作,通常放在线程中执行,你可以自己
new Thread(){run()}.start() ,
其实retrofit已经封装了线程请—enqueue( )
button.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl( “https://api.github.com/” )
.build();
GitHubApi repo = retrofit.create( GitHubApi.class );//拿到接口对象,反射代理机制
Call call = repo.get( “square”, “retrofit” );//get方法已经被重写了
//使用call进行请求
call.enqueue( new Callback() {
@Override
public void onResponse(Response response, Retrofit retrofit) {
try {
response.body().string()—” + response.body().string() );
}
} catch (IOException e) {
Log.d( “lihui”, “e—” + e.toString() );
e.printStackTrace();
}
}
@Override
public void onFailure(Throwable t) {
Log.d( “lihui”, “t—” + t.toString() );
}
} );
分析:
call.enqueue( )这个是异步请求。
call也支持同步请求,
Call call = repo.get();
ResponseBody responseBody= call.execute();
这里:call.execute()返回对象模板关系
Call<T>
T t=call.execute();
但是android会抛出异常
阻塞线程,因此你不能在安卓的主线程中调用,不然会面临NetworkOnMainThreadException。如果你想调用execute方法,请在后台线程执行。
如果返回的数据是json格式,
可以对response.body()返回的数据进行反序列化,
使用json包
compile ‘com.google.code.gson:gson:2.3’
Gson gson = new Gson();
ArrayList<Contributor> contributorsList = gson.fromJson( response.body().string(), new TypeToken<List<Contributor>>() {
}.getType() );
Contributor实体类,对应
public class Contributor {
private String login;
private String contributions;
private String html_url;
private String avatar_url;
public String getAvatar_url() {
return avatar_url;
}
public void setAvatar_url(String avatar_url) {
this.avatar_url = avatar_url;
}
public Contributor(String login) {
this.login = login;
}
public String getHtml_url123() {
return html_url;
}
public void setHtml_url123(String html_url) {
this.html_url = html_url;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getContributions() {
return contributions;
}
public void setContributions(String contributions) {
this.contributions = contributions;
}
}
这里面的属性名称一定要和json中name一致!!!!
其实retrofit中已经有了json转化器,自动将返回的json格式数据进行序列化。
修改:
@GET("repos/{owner}/{repo}/contributors")
Call<List<Contributor>> get(@Path("owner") String owner, @Path("repo") String repo);
Retrofit retrofit = new Retrofit.Builder().baseUrl( "https://api.github.com/" ).
**addConverterFactory**( GsonConverterFactory.create() ).build();
addConverterFactory:转化器
对应jar包:
compile ‘com.squareup.retrofit:converter-gson:2.0.0-beta2’
返回处理:
public void onResponse(Response<List<Contributor>> response, Retrofit retrofit) {
List<Contributor> contributors = response.body();//已经向返回的数据进行了序列化
for (Contributor contributor : contributors) {
Log.d( "lihui", "1---" + contributor.getLogin() );
Log.d( "lihui", "2---" + contributor.getContributions() );
Log.d( "lihui", "3---" + contributor.getHtml_url123() );
}
}
4、结合rxjava+rxandroid
修改如下:
1)jar包
compile ‘com.squareup.retrofit:adapter-rxjava:2.0.0-beta2’
适配器
2)@GET("repos/{owner}/{repo}/contributors")
rx.Observable<List<Contributor>> getSource(@Path("owner") String owner, @Path("repo") String repo);
模板2,返回对象Observable
Retrofit retrofit = new Retrofit.Builder().baseUrl( "https://api.github.com/" ). addCallAdapterFactory( **RxJavaCallAdapterFactory**.create() ). addConverterFactory( GsonConverterFactory.create() ).build();
注:
addCallAdapterFactory添加适配工厂,这样rxjava中可以直接传递List对象了。
button3.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
Retrofit retrofit = new Retrofit.Builder().baseUrl( "https://api.github.com/" ).
addCallAdapterFactory( RxJavaCallAdapterFactory.create() ). addConverterFactory( GsonConverterFactory.create() ).build();
GitHubApi mGitHubService = retrofit.create( GitHubApi.class ); mGitHubService.getSource( "square", "retrofit" ).subscribeOn( Schedulers.io() ).observeOn( AndroidSchedulers.mainThread() ).subscribe( new Observer<List<Contributor>>() {
@Override
public void onCompleted() {}
@Override
public void onError(Throwable e) {}
@Override
public void onNext(List<Contributor> contributors) {
for (Contributor c : contributors) {
Log.d( "lihui", "Contributions---" + c.getContributions() );
}
}
} );
}
}
);
注:
addCallAdapterFactory
返回的数据可以结合rxjava的Observeble数据传递下去。
2016-12-1 笔记:
retrofit结合使用rxjava,
必须添加
.addCallAdapterFactory( RxJavaCallAdapterFactory.create() )
否则出现异常:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.lihui20.testhttp, PID: 6397
java.lang.IllegalArgumentException: *Unable to create call adapter for* rx.Observable<com.squareup.okhttp.ResponseBody>
for method GitHubApi.getLocation
at retrofit.Utils.methodError(Utils.java:177)
at retrofit.MethodHandler.createCallAdapter(MethodHandler.java:47)
at retrofit.MethodHandler.create(MethodHandler.java:26)
at retrofit.Retrofit.loadMethodHandler(Retrofit.java:151)
at retrofit.Retrofit$1.invoke(Retrofit.java:132)
at java.lang.reflect.Proxy.invoke(Proxy.java:813)
at $Proxy0.getLocation(Unknown Source)
at com.example.lihui20.testhttp.MainActivity$4.onClick(MainActivity.java:161)
at android.view.View.performClick(View.java:5609)
at android.view.View$PerformClick.run(View.java:22279)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6111)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for rx.Observable<com.squareup.okhttp.ResponseBody>. Tried:
* retrofit.ExecutorCallAdapterFactory
at retrofit.Retrofit.nextCallAdapter(Retrofit.java:207)
at retrofit.Retrofit.callAdapter(Retrofit.java:175)
at retrofit.MethodHandler.createCallAdapter(MethodHandler.java:45)
... 15 more
java.lang.IllegalArgumentException: Unable to create call adapter for rx.Observable
Call<ResponseBody>
结果返回不是json格式,我们想转换成其他类型,如:
Call
Process: com.example.lihui20.testhttp, PID: 11899
java.lang.IllegalArgumentException: **Unable to create converter for class java.lang.String**
for method GitHubApi.getLocation
at retrofit.Utils.methodError(Utils.java:177)
at retrofit.MethodHandler.createResponseConverter(MethodHandler.java:57)
at retrofit.MethodHandler.create(MethodHandler.java:29)
at retrofit.Retrofit.loadMethodHandler(Retrofit.java:151)
at retrofit.Retrofit$1.invoke(Retrofit.java:132)
at java.lang.reflect.Proxy.invoke(Proxy.java:813)
at $Proxy0.getLocation(Unknown Source)
at com.example.lihui20.testhttp.MainActivity$4.onClick(MainActivity.java:162)
at android.view.View.performClick(View.java:5609)
at android.view.View$PerformClick.run(View.java:22279)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6111)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Caused by: java.lang.IllegalArgumentException: Could not locate ResponseBody converter for class java.lang.String. Tried:
* retrofit.BuiltInConverters
at retrofit.Retrofit.responseConverter(Retrofit.java:266)
at retrofit.MethodHandler.createResponseConverter(MethodHandler.java:55)
... 15 more
自定义
converter for class java.lang.String
.addConverterFactory( new Converter.Factory() {
@Override
public Converter<ResponseBody, ?> fromResponseBody(Type type, Annotation[] annotations) {
return new Converter<ResponseBody, String>() {
@Override
public String convert(ResponseBody value) throws IOException {
return value.string();
}
};
}
} )
rxjava运算符学习:
1)just和from
直接上例子
List<Integer> list2 = new ArrayList<Integer>();
list2.add( 123 );
list2.add( 34 );
Observable.from( list2 ).subscribe( new Action1<Integer>() {
@Override
public void call(Integer integer) {
Log.d("lihui","from---"+ integer);
}
} );
分析:
call方法会连续调用多次,循环把list中item输出。
12-02 17:04:31.958 13858-13858/com.example.lihui20.testhttp D/lihui: from---123
12-02 17:04:31.958 13858-13858/com.example.lihui20.testhttp D/lihui: from---34
Observable.just(list2 ).subscribe( new Action1<List<Integer>>() {
@Override
public void call(List<Integer> integers) {
Log.d("lihui","just---"+ integers.toString() );
}
} );
分析:
修改call方法—
直接传递
List integers 对象
自定义的
public void call(List integers)
调用一次。