通过使用Retrofit+RxJava和Volley获取,比较两者的使用区别。
文中 RR:代指Retrofit+Rxjava
主要两个方面使用
- 使用两者获取Json数据,使用Gson解析。
- 使用两者获取网络图片
1.第一步添加RR和Volley的gradle依赖
//google's volleycompile 'com.mcxiaoke.volley:library:1.0.19'//RxAndroidcompile 'io.reactivex:rxandroid:1.2.1'//RxJavacompile 'io.reactivex:rxjava:1.2.3'//Retrofitcompile 'com.squareup.retrofit2:retrofit:2.1.0'compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'compile 'com.squareup.retrofit2:converter-gson:2.1.0'
2.分析知乎首页Api返回的Json格式
Api:
3.构建bean
在AndroidStudio里我是使用一个Json2Pojo插件,可以直接将Json对象转换为适合Gson的JavaBean
在AS的插件管理里可以直接安装 Json2Pojo
/** * 知乎当日消息 */public class Stories { //供 Google Analytics 使用 @SerializedName("ga_prefix") private String mGaPrefix; //url 与 share_url 中最后的数字(应为内容的 id) @SerializedName("id") private Long mId; //图像地址(官方 API 使用数组形式。目前暂未有使用多张图片的情形出现,曾见无 images 属性的情况,请在使用中注意 ) @SerializedName("images") private ListmImages; //消息是否包含多张图片(仅出现在包含多图的新闻中) @SerializedName("multipic") private Boolean mMultipic; //消息标题 @SerializedName("title") private String mTitle; //作用未知 @SerializedName("type") private Long mType; public Stories(String mGaPrefix, Long mId, List mImages, Boolean mMultipic, String mTitle, Long mType) { this.mGaPrefix = mGaPrefix; this.mId = mId; this.mImages = mImages; this.mMultipic = mMultipic; this.mTitle = mTitle; this.mType = mType; } public void setGaPrefix(String mGaPrefix) { this.mGaPrefix = mGaPrefix; } public void setId(Long mId) { this.mId = mId; } public void setImages(List mImages) { this.mImages = mImages; } public void setMultipic(Boolean mMultipic) { this.mMultipic = mMultipic; } public void setTitle(String mTitle) { this.mTitle = mTitle; } public void setType(Long mType) { this.mType = mType; } public String getGaPrefix() { return mGaPrefix; } public Long getId() { return mId; } public List getImages() { return mImages; } public Boolean getMultipic() { return mMultipic; } public String getTitle() { return mTitle; } public Long getType() { return mType; } @Override public String toString() { return "Stories{" + "mGaPrefix='" + mGaPrefix + '\'' + ", mId=" + mId + ", mImages=" + mImages + ", mMultipic=" + mMultipic + ", mTitle='" + mTitle + '\'' + ", mType=" + mType + '}'; }}
4.定义Retrofit和Volley的单例管理
获取Retrofit单例
public class RetrofitManager { static final String BASE_URL = "http://news-at.zhihu.com/api/4/news/"; private Retrofit retrofit; private static RetrofitManager ourInstance = new RetrofitManager(); public static RetrofitManager getInstance() { return ourInstance; } private RetrofitManager() { } /** * 获取retrofit单例 * * @return Retrofit single */ public Retrofit getRetrofit() { if (retrofit == null) { retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build(); } return retrofit; }}
获取Volley RequestQueue单例
public class VolleyManager { private RequestQueue requestQueue; private static VolleyManager ourInstance = new VolleyManager(); public static VolleyManager getInstance() { return ourInstance; } private VolleyManager() { } /** * 获取 volley requestQueue 单例 * * @param context activity * @return volley requestQueue */ public RequestQueue getRequestQueue(Context context) { if (requestQueue == null) { requestQueue = Volley.newRequestQueue(context); } return requestQueue; }}
5.定义Retrofit REST Api 接口
//获取Json数据public interface GetNews { @GET("latest") ObservablegetNews();}//获取图片public interface GetBitmap { @GET Observable getPicFromNet(@Url String url);}这里使用RxJava形式的接口定义,直接返回 被观察者对象
6.获取Json数据,并返回Result对象
通过RR获取
//get data by Retrofit & RxJavaprivate void getDataByRetrofit() { progressBar.setVisibility(View.VISIBLE); storiesAdapter.setGetPicByRR(true);// tell adapter get pic by retrofit //RR:Retrofit+RxJava Subscribersubscriber = new Subscriber () { @Override public void onCompleted() { } @Override public void onError(Throwable e) { progressBar.setVisibility(View.INVISIBLE); Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show(); } @Override public void onStart() { super.onStart(); storiesList.clear(); } //设置数据到RecyclerView @Override public void onNext(Result result) { storiesList.addAll(result.getStories()); storiesAdapter.notifyDataSetChanged(); progressBar.setVisibility(View.INVISIBLE); } }; //主要逻辑 GetNews getNews = RetrofitManager.getInstance().getRetrofit().create(GetNews.class); getNews.getNews() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(subscriber);}
通过Volley获取
/** * get data by volley */private void getDataByVolley() { progressBar.setVisibility(View.VISIBLE); storiesAdapter.setGetPicByRR(false);// tell adapter get pic by volley //主要逻辑 StringRequest stringRequest = new StringRequest(Request.Method.GET, RetrofitManager.BASE_URL + "latest", new Response.Listener() { @Override public void onResponse(String response) { //Json to Bean Gson gson = new Gson(); Result result = gson.fromJson(response, Result.class); storiesList.addAll(result.getStories()); //设置数据到RecyclerView storiesAdapter.notifyDataSetChanged(); progressBar.setVisibility(View.INVISIBLE); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Toast.makeText(context, error.getMessage(), Toast.LENGTH_SHORT).show(); } }); VolleyManager.getInstance().getRequestQueue(this.getApplication()).add(stringRequest);}
7.Adapter中获取图片
通过RR获取
//get pic by Retrofit and RxJava Action1bitmapAction1 = new Action1 () { @Override public void call(Bitmap bitmap) { holder.ivImg.setImageBitmap(bitmap); } }; String url = stories.getImages().get(0); GetBitmap getBitmap = RetrofitManager.getInstance().getRetrofit().create(GetBitmap.class); getBitmap.getPicFromNet(url) .map(new Func1 () { @Override public Bitmap call(ResponseBody responseBody) { //decode pic return BitmapFactory.decodeStream(responseBody.byteStream()); } }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(bitmapAction1);
通过Volley获取
//get pic by volley ImageLoader imageLoader = new ImageLoader(VolleyManager.getInstance() .getRequestQueue(context.getApplicationContext()) , new ImageLoader.ImageCache() { @Override public Bitmap getBitmap(String url) { return null; } @Override public void putBitmap(String url, Bitmap bitmap) { } }); ImageLoader.ImageListener imageListener = ImageLoader.getImageListener(holder.ivImg, R.mipmap.ic_launcher, R.mipmap.ic_launcher); String url = stories.getImages().get(0); imageLoader.get(url, imageListener);
8.总结
这里只是从简单的使用层面上对比了RR和Volley两者使用上的不同,之前获取网络数据的任务都是交给Volley来做。
有时获取了A数据之后,马上需要进行下一步包装分析A之后获取B数据。 如果是在Volley中就会出现嵌套的逻辑;在RxJava中使用Retrofit就可以使用它的map(或flatMap)进行A数据的包装分析,之后返回B数据的,就不会出现嵌套的逻辑。以上只是小生简单的对比,用以自身理解RxJava,有什么不对的地方欢迎各位指出 ^_^