美文网首页小技巧Java Worldokhttp
我们真的需要使用RxJava+Retrofit吗?

我们真的需要使用RxJava+Retrofit吗?

作者: IAM四十二 | 来源:发表于2016-12-04 16:30 被阅读3630次
    Android.jpg

    前言

    可以说RxJava+Retrofit是整个2016年Android 开发圈内最受关注的的组合。各大Android论坛上有大量以RxJava+Retrofit+xxx 为标题的文章,此类文章也备受大家的关注。这个组合仿佛已经成为了Android开发的必备组件,项目里没使用这个组合好像自己都out了似的。

    平心而论,RxJava和Retrofit 相较于以往的各种框架(如 AsyncHttpClient,Volley等 )学习和使用起来会有一些难度;RxJava 强大而又庞大的操作符,Retrofit采用注解风格定义接口,都会让初学者花费不少功夫,绕不少圈子,踩大量的坑。既然这样,那么就会有人怀疑,我们真的需要学习RxJava和Retrofit吗?

    任意一款需要联网的APP,最典型的套路就是请求后端数据,解析数据进行UI更新;响应用户操作,再次请求数据,更新UI。这里我们就从最基础的网络请求出发,带着疑问,逐步了解一下Retrofit的前生今世,看一看RxJava和Retrofit的价值所在。

    Android Http

    最基础的实现方式

    初学Android开发时,还在上大学,那会儿还不知有AsyncHttpClient,Volley,OKHttp 这么方便的框架;一个简单的网络请求通常要写一大段代码。

    使用HttpURLConnection实现网络请求####

    class MyTask extends AsyncTask<String, Void, String> {
    
            @Override
            protected String doInBackground(String... params) {
                InputStream mInputStream = null;
                HttpURLConnection connection = getHttpUrlConnection(params[0]);
                String result = "";
                try {
                    connection.connect();
                    int statusCode = connection.getResponseCode();
                    String response = connection.getResponseMessage();
                    mInputStream = connection.getInputStream();
                    InputStreamReader inputStreamReader = new InputStreamReader(mInputStream);
                    BufferedReader reader = new BufferedReader(inputStreamReader);
                    StringBuffer sb = new StringBuffer();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        sb.append(line + "\n");
                    }
    
                    result = "StatusCode: " + statusCode + "\n"
                            + "Response" + response + "\n"
                            + sb.toString();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return result;
            }
    
            @Override
            protected void onPostExecute(String s) {
                super.onPostExecute(s);
                tv.setText(s);
            }
        }
    
        private HttpURLConnection getHttpUrlConnection(String url) {
            HttpURLConnection connection = null;
            try {
                URL mUrl = new URL(url);
                connection = (HttpURLConnection) mUrl.openConnection();
                connection.setConnectTimeout(20000);
                connection.setReadTimeout(40000);
                connection.setRequestMethod("GET");
                connection.setRequestProperty("Content-Type", "application/json");
                connection.setRequestProperty("Accept", "application/json");
                connection.setRequestProperty("Charset", "utf-8");
                connection.setRequestProperty("Content-Length", "0");
    
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            return connection;
        }
    
    new MyTask().execute(BASE_URL);
    

    这段代码的逻辑很简单,就是将网络请求的结果显示在一个TextView上。很大一部分的内容都是在执行HttpURLConnection 相关的配置及初始化工作。

    记得第一次通过网络请求把数据显示的Android模拟器(那时候还是穷学生,买不起Android手机)的屏幕上时,虽然只是一大堆别人看不懂的json字符串,但是感觉自己就要上天了,现在想想真是。。。。。

    即便是这么长的一段代码,还没有包含网络请求异常的内容,如果加上网络请求失败处理的逻辑,将使得整个代码结构更加臃肿庞大。

    网络请求框架的涌现###

    一款联网的APP至少会有十几次的网络请求,更多的就无法估计了。因此,每一次的网络请求不可能像上面那样写。因此,我们需要封装,将一些固定的操作统一处理,当然已经有许多大神比我早想到了这个问题,因此便出现了许多对网络请求进行封装的库。

    • AsyncHttpClient(底层基于HttpClient)
    • afinal(FinalHttp,同样是基于HttpClient封装)
    • xUtils (基于afinal)
    • Volley(Google官方出品)
    • okHttp
    • NoHttp (个人开发)

    这里列出的几个库当中,个人使用AsyncHttpClient较多,AsyncHttpClient 的确非常好用,但是后来伴随着Android sdk 23 中HttpClient的废弃也逐渐被遗忘。
    afinal和xUtils 都没有在实际项目中没用过,不做评价。

    Volley作为Google官方在2013年I/O 大会上推出的库,相较于AsyncHttpClient 更强大。

    下面简单列举一个使用Volley进行get请求的demo。

    Volley 简单使用####

    添加依赖:

    compile 'com.mcxiaoke.volley:library:1.0.19'
    
    protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mContext = this;
            queue = Volley.newRequestQueue(mContext);
            setContentView(R.layout.activity_http_volley_demo);
            tv = (TextView) findViewById(R.id.editText);
    
            final StringRequest request = new StringRequest(Request.Method.GET, BASE_URL,
                    new ResponseSuccessListener(), new ResponseFailListener());
            findViewById(R.id.volley).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    queue.add(request);
                }
            });
    
        }
    
        private class ResponseSuccessListener implements com.android.volley.Response.Listener<String> {
    
            @Override
            public void onResponse(String response) {
                tv.setText(response);
            }
        }
    
        private class ResponseFailListener implements Response.ErrorListener {
    
            @Override
            public void onErrorResponse(VolleyError error) {
                Toast.makeText(mContext, error.toString(), Toast.LENGTH_SHORT).show();
            }
        }
    

    这段代码和上面的功能一样,都是将网络请求的结果显示在TextView。但是通过Volley对http请求进行一次封装后,我们不再关注网络请求的具体细节,而是将重点放在了对请求结果的处理上;网络请求无论成功还是失败,我们都可以很多好的应对。

    而且在Volley中,异步网络请求的回调方法已然处于UI线程中,这样我们就可以直接在回调方法中进行UI更新了。

    可以说,使用Volley已经可以非常方便的处理Android 网络请求的相关内容了。既然如此,为什么还会有OKHttp和Retrofit的出现呢?他们的优势又在哪里呢?

    OKHttp 简单介绍####

    okHttp 是由squire 推出的一个网络请求库,包括Retrofit也是由其开发,这里为squire点个赞。

    使用之前加入依赖

        compile 'com.squareup.okhttp3:okhttp:3.4.1'
        compile 'com.squareup.okio:okio:1.11.0'
    

    okHttp 网络请求实现

    findViewById(R.id.get).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    tv.setText("");
                    loading.setVisibility(View.VISIBLE);
                    client = new OkHttpClient();
                    Request.Builder builder = new Request.Builder()
                            .url(BASE_URL)
                            .method("GET", null);
    
                    request = builder.build();
                    Call mCall = client.newCall(request);
                    mCall.enqueue(new MyCallback());
                }
            });
    
    private class MyCallback implements Callback {
    
            @Override
            public void onFailure(Call call, IOException e) {
                Message msg = new Message();
                msg.what = 100;
                msg.obj = e;
                handler.sendMessage(msg);
            }
    
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Message msg = new Message();
                msg.what = 200;
                msg.obj = response.body().string();
                handler.sendMessage(msg);
            }
        }
    
    class MyHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                loading.setVisibility(View.GONE);
                switch (msg.what) {
                    case 100:
                        Object e = msg.obj;
                        Toast.makeText(mContext, e.toString(), Toast.LENGTH_SHORT).show();
                        break;
                    case 200:
                        String response = (String) msg.obj;
                        tv.setText(response);
                        break;
                    case 300:
                        int percent = msg.arg1;
                        Log.e("llll", "the percent is " + percent);
                        if (percent < 100) {
                            progressDialog.setProgress(percent);
                        } else {
                            progressDialog.dismiss();
                            Glide.with(mContext).load(FILE_PATH).into(imageView);
                        }
                        break;
                    default:
                        break;
                }
            }
        }
    

    这里必须了解的是,okHttp的回调方法,并不处于UI 线程中,对网络请求结果如果涉及UI 线程的操作,需要使用Handler。这么看来,okHttp 貌似反而不如Volley了。其实不然,okhttp的封装套路和Volley,AsyncHttp不是一个级别的,不能和后两者作比较,okhttp 和HttpClient、HttpUriConneciton 才是一个级别的产物,相较于这两者,okhttp显然强大了许多。

    所以,OKHttp不仅仅可以用于Android开发,Java开发也是OK的。

    Retrofit

    A type-safe HTTP client for Android and Java

    一个针对Android和Java类型安全的http客户端

    上面这句话,就是Squire对Retrofit的说明,言简意赅。Retrofit其实是对okhttp 做了进一步的封装,有了okhttp 的基础,使用Retrofit会很容易。

    下面就来看看,使用Retrofit做网络请求又是一种怎样的体验。

    这里为了方便我们使用"https://api.github.com/"作为网络请求的接口基地址

    使用之前加入依赖:

    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    

    定义接口

    public interface GithubService {
    
        @GET("users/{user}")
        Call<ResponseBody> getUserString(@Path("user") String user);
    
    }
    

    这里我们使用http中的get 方法获取users这个接口下,当前user的具体信息,参数为当前user名。返回内容为Http请求的ResponseBody。

    Retrofit 返回ResponseBody

    private void SimpleRetrofit() {
            OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
            Retrofit.Builder builder = new Retrofit.Builder()
                    .baseUrl(BASE_URL);
            Retrofit retrofit = builder.client(httpClient.build()).build();
            GithubService simpleService = retrofit.create(GithubService.class);
            Call<ResponseBody> call = simpleService.getUserString(name);
            call.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                    loading.dismiss();
                    try {
                        String result = response.body().string();
                        Gson gson = new Gson();
                        GithubUserBean bean = gson.fromJson(result, GithubUserBean.class);
                        setUserView(bean);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
    
                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
                    loading.dismiss();
                }
            });
        }
    
    private void setUserView(GithubUserBean user) {
            if (user != null) {
                viewShell.removeAllViews();
                View view = LayoutInflater.from(mContext).inflate(R.layout.user_item_layout, null);
                TextView title = (TextView) view.findViewById(R.id.title);
                TextView id = (TextView) view.findViewById(R.id.userId);
                TextView creteaTime = (TextView) view.findViewById(R.id.createTime);
                TextView updateTime = (TextView) view.findViewById(R.id.updateTime);
                TextView bio = (TextView) view.findViewById(R.id.bio);
                ImageView avatar = (ImageView) view.findViewById(R.id.avatar);
    
                title.setText("Name: " + user.getLogin());
                bio.setText("Bio: " + user.getBio());
                id.setText("Id: " + String.valueOf(user.getId()));
                creteaTime.setText("createTime: " + user.getCreated_at());
                updateTime.setText("updateTime: " + user.getUpdated_at());
                Glide.with(mContext).load(user.getAvatar_url()).into(avatar);
    
                viewShell.addView(view);
            } else {
                Toast.makeText(mContext, "result is null", Toast.LENGTH_SHORT).show();
            }
        }
    

    GitHubUserBean 为网络请求结果json数据所对应的实体类。

    通过这段代码,我们在最终的回调方法里可以友好的处理请求结果,失败时onFailure方法执行。成功时,onResponse方法执行,我们在这里用Gson解析返回的数据,并进行UI更新操作(setUserView(bean)),

    这里我们这样做有些啰嗦,Gson转换的方式都是类似,唯一不同的只是每次网络请求结果对应的实体类;因此我们可以借助强大的Retrofit帮助我们完成Gson转换的步骤。当然,如果在你所在的开发环境中,接口返回的并不是json格式的数据,也没有问题的。

    convertconvert

    上图是Retrofit官网对可转换类型给出的介绍。有这么多种,当然了如果你们家服务器返回的数据格式比较神奇,你也可以自定义转换类。

    好了,言归正传,这里还是以Json 格式数据为例。

    添加依赖:

    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    

    注意这里converter-gson 的版本号,要和之前Retrofit的版本号保持一致。

    我们重新定义接口:

    public interface GithubService {
        @GET("users/{user}")
        Call<GithubUserBean> getUser(@Path("user") String user);
    
    }
    

    这里我们用GithubUserBean取代ResponseBody,直接将其作为返回类型。

    Retrofit 返回对象

    private void LazyRetrofit() {
            OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
            Retrofit.Builder builder = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create());
            Retrofit retrofit = builder.client(httpClient.build()).build();
            GithubService service = retrofit.create(GithubService.class);
            Call<GithubUserBean> call = service.getUser(name);
            call.enqueue(new Callback<GithubUserBean>() {
                @Override
                public void onResponse(Call<GithubUserBean> call, Response<GithubUserBean> response) {
                    GithubUserBean bean = response.body();
                    setUserView(bean);
                    loading.dismiss();
                }
    
                @Override
                public void onFailure(Call<GithubUserBean> call, Throwable t) {
                    loading.dismiss();
                }
            });
        }
    

    这里的实现方式和上面基本相似,只是多了一行

    .addConverterFactory(GsonConverterFactory.create());
    

    这样,我们在onResponse中获得就是对象,不再需要做额外的转换工作,可以直接使用。

    Retrofit 简单封装

    这里我们可以看到,Retrofit使用有着一定的套路,所以我们可以将Retrofit初始化相关得内容做一次简单的封装。

    public class GenServiceUtil {
        private static final String BASE_URL = "https://api.github.com/";
    
        private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
    
        private static Retrofit.Builder builder = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create());
    
        private static Retrofit retrofit = builder.client(httpClient.build()).build();
    
        public static <S> S createService(Class<S> serviceClass) {
            return retrofit.create(serviceClass);
        }
    
    }
    
    private void EasyRetrofit() {
            GithubService service = GenServiceUtil.createService(GithubService.class);
            Call<GithubUserBean> call = service.getUser(name);
            call.enqueue(new Callback<GithubUserBean>() {
                @Override
                public void onResponse(Call<GithubUserBean> call, Response<GithubUserBean> response) {
                    GithubUserBean bean = response.body();
                    loading.dismiss();
                    setUserView(bean);
                }
    
                @Override
                public void onFailure(Call<GithubUserBean> call, Throwable t) {
                    loading.dismiss();
                }
            });
        }
    
    

    我们只需传入定义好的借口,会使代码简介许多。看到这里可以发现,Retrofit的确很厉害,那为什么又要将他和RxJava结合在一起呢?下面我们就来看看。

    RxJava+Retrofit

    关于什么是RxJava,这里不再赘述,不了解的看以看看这里。这里我们就看看将RxJava 和我们之前的内容结合在一起会有怎样的效果。

    首先,加入依赖

        compile 'io.reactivex:rxjava:1.1.7'
        compile 'io.reactivex:rxandroid:1.2.1'
    

    RxJava+Retrofit 实现###

    private void RxRetrofit() {
            GithubService service = GenServiceUtil.createService(GithubService.class);
            final Call<GithubUserBean> call = service.getUser(name);
            final Observable myObserable = Observable.create(new Observable.OnSubscribe<GithubUserBean>() {
                @Override
                public void call(Subscriber<? super GithubUserBean> subscriber) {
                    Response<GithubUserBean> bean = null;
                    try {
                        bean = call.execute();
                        subscriber.onNext(bean.body());
    
                    } catch (IOException e) {
                        e.printStackTrace();
                        subscriber.onError(e);
                    }
    
                    subscriber.onCompleted();
                }
            });
    
            myObserable
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .map(new Func1<GithubUserBean, GithubUserBean>() {
                        @Override
                        public GithubUserBean call(GithubUserBean o) {
                            if (TextUtils.isEmpty(o.getBio())) {
                                o.setBio("nothing !");
                            }
                            return o;
                        }
                    })
                    .subscribe(new Subscriber<GithubUserBean>() {
                        @Override
                        public void onCompleted() {
                            loading.dismiss();
                        }
    
                        @Override
                        public void onError(Throwable e) {
                            loading.dismiss();
                        }
    
                        @Override
                        public void onNext(GithubUserBean o) {
                            setUserView(o);
                        }
                    });
    
        }
    

    这里有几点需要注意:

    • RxJava 本身最大的特定就是异步,因此这里我们Retrofit执行网络请求的时候,使用了execute(同步请求),而不再是enqueue。
    • RxJava 可以使用subscribeOn和observeOn完美处理Observeable和Subscribe的执行线程问题。
    • 这里使用RxJava中map操作符,对返回内容中的为null或“” 的对象做了简单的处理。

    我们引入RxJava实现了同样的功能,却使得代码量增加了很多。不禁要问,RxJava的价值到底在哪里呢?

    RxJava + Retrofit 到底好在哪里

    好了,为了说明为题,我们添加一个接口

    public interface GithubService {
    
        @GET("users/{user}")
        Call<GithubUserBean> getUser(@Path("user") String user);
    
        @GET("users/{user}/followers")Observable<List<UserFollowerBean>> followers(@Path("user") String usr);
    
    }
    

    当然这里依旧需要添加依赖:

    compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
    

    同时在Service的封装方法中添加

    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
    

    这样,RxJava就和Retrofit完美的关联在了一起。

    我们在接口中,定义followers()方法直接返回了Observable,因为Observable是RxJava的源头,而且Retrofit可以很好的支持RxJava,这样就非常方便了。

        private void RxRetrofitList() {
            GithubService service = GenServiceUtil.createService(GithubService.class);
            Observable<List<UserFollowerBean>> myObserve = service.followers(name);
            myObserve
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Subscriber<List<UserFollowerBean>>() {
                        @Override
                        public void onCompleted() {
                            loading.dismiss();
                        }
    
                        @Override
                        public void onError(Throwable e) {
                            loading.dismiss();
                            e.printStackTrace();
                        }
    
                        @Override
                        public void onNext(List<UserFollowerBean> userFollowerBeen) {
                            setFollowersView(userFollowerBeen);
                        }
                    });
    
        }
    

    在接口中返回的内容就是Observable,因此不用再像之前一样单独定义Observable;在onNext 方法中,接收到返回的对象,更新UI。 这里如果我们不使用RxJava,单独使用Retrofit实现这个过程是没有任何问题的; RxJava看似没有价值;但是假设现在出现如下之一的情景

    • 需要对返回的userFollowerBeen 这个list 进行按用户名从小到大的排序
    • 需要对返回的userFollowerBeen 这个list 进行按用户ID从小到大的排序
    • 如果返回的userFollowerBeen 这个list 中,某一项的头像地址为空,则不显示该项

    .....

    这种情景在实际开发中太常见了,试想如果没有RxJava;那么每一次需求的变更都意味着我们需要去修改setFollowersView这个方法,需求一旦变更,就去修改这个方法,这样会不可避免的产生各种bug。那有没有办法不去修改这个方法呢?这个时候,就需要强大的RxJava了。

    这里我们就看看如何在不修改setFollowersView的前提下,实现对用户名从小到大的排序:

        private void RxRetrofitList() {
            GithubService service = GenServiceUtil.createService(GithubService.class);
            Observable<List<UserFollowerBean>> myObserve = service.followers(name);
            myObserve
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .map(new Func1<List<UserFollowerBean>, List<UserFollowerBean>>() {
                        @Override
                        public List<UserFollowerBean> call(List<UserFollowerBean> userFollowerBeen) {
                            for (UserFollowerBean bean : userFollowerBeen) {
                                String name = "";
                                name = bean.getLogin().substring(0, 1).toUpperCase() + bean.getLogin().substring(1, bean.getLogin().length());
                                bean.setLogin(name);
                            }
                            return userFollowerBeen;
                        }
                    })
                    .map(new Func1<List<UserFollowerBean>, List<UserFollowerBean>>() {
                        @Override
                        public List<UserFollowerBean> call(List<UserFollowerBean> userFollowerBean) {
                            Collections.sort(userFollowerBean, new Comparator<UserFollowerBean>() {
                                @Override
                                public int compare(UserFollowerBean o1, UserFollowerBean o2) {
                                    return o1.getLogin().compareTo(o2.getLogin());
                                }
                            });
                            return userFollowerBean;
                        }
                    })
                    .subscribe(new Subscriber<List<UserFollowerBean>>() {
                        @Override
                        public void onCompleted() {
                            loading.dismiss();
                        }
    
                        @Override
                        public void onError(Throwable e) {
                            loading.dismiss();
                            e.printStackTrace();
                        }
    
                        @Override
                        public void onNext(List<UserFollowerBean> userFollowerBeen) {
                            setFollowersView(userFollowerBeen);
                        }
                    });
    
        }
    

    在代码中我们使用RxJava的map 操作符,对返回数据做了两次处理,首先将所有用户名的首字母转换为大写字母;然后对整个list按照用户名从小到大排序。因为用户名中同时包含以大小写字母打头的内容,所以为了方便,我们进行了一次转换大写的操作。

    同样是随着需求变更,修改代码;但是你会发现,使用RxJava的方式,会降低出现bug的概率,而且就算是不同的人去改,也会比较方便维护。

    看到了吧,这就是RxJava的优点,当然这个例子也只是冰山一角。这里提到的map操作符只是RxJava庞大操作符集合中的一员,更特别的是,RxJava的操作符还是可以自定义的,这样让我们的代码有了无限的可能;RxJava的存在不仅仅在于网络请求,可以用在别的方面;RxJava其实是体现了一种思路,所有对数据的操作都在流上完成,将最终的结果返回给观察者。同时,如果返回的followers 列表有任何异常,RxJava的onError 方法会执行,这就方便我们去处理异常数据了。

    总结##

    通篇通过对Android 网络请求各种实现的总结,可以看到 相对于Volley,AsyncHttpClient 等库,RxJava+Retrofit 的优势并非特别显著;在执行效率及功能上并无大的亮点;对Volley进行良好的封装同样可以实现类似Retrofit自动转Gson的功能;RxJava+Retrofit 结合会让我们写代码的方式更加有条理,虽然代码量会增多,但逻辑的清晰才是最重要的不是吗?所以,RxJava+Retrofit 组合不失为一种好的选择。

    所以,RxJava+Retrofit 真的是我们需要的东西呀!


    文中所有源码地址github

    相关文章

      网友评论

      • 宇宙只有巴掌大:rxjava强大在于他的数据流试的操作,整个过程依靠数据的流向处理结构清晰,而retrofit这种注解试的网络请求,支持被观察者的返回(相当于返回数据源)的这种方式让我们只需要关心业务逻辑的处理,如果配合mvp会给整体代码结构带来很清晰的层次感。
      • jdsjlzx:写的很认真,赞一个!
        IAM四十二:@jdsjlzx 谢谢,:smile:
      • 无余:rxjava+retrofit时怎么获取header中的信息?
        只用retrofit时倒是很容易,但是结合rxjava就不知怎么搞了,本来想通过ConverterFactory实现的,发现这一步已经是ResponBody了,
        难道要让服务端不要在header中存数据,或者再需要获取header中数据时不用rxjava?
        IAM四十二:RxJava 只是提供了一种写代码的模式,或者说是套路;真正的网络请求还是在Retrofit中,不要为了RxJava而去RxJava;在Retrofit中已经可以了,何必硬往RxJava上套
      • 微凉一季:流式操作,流上操作的多了,是不是不好找bug
        微凉一季:@IAM四十二 很多时候根本分不清bug是在哪出的问题啊,这么多分开的操作得一个一个看啊
        IAM四十二: @微凉一季 我怎么感觉是更好找,都在流上,每一步都有明确的业务
      • 恨自己不能小清新:哪能解释下会需要RxJava+OkHttp+Retrofit吗?Retrofit网络请求是OkHttp,为啥还需要OkHttp?还有Dagger2 + DataBinding这两个不都是注解吗?为啥需要Dagger2 + DataBinding这样用?谢谢 :relaxed:
        e8a031d91ef0:其实okhttp那段代码可以省下不写的呢,纯属建议:smile:
        恨自己不能小清新:@IAM四十二 好的 谢谢
        IAM四十二:@恨自己不能小清新 Retrofit 其实对OKHttp的进一步封装,Retrofit 只是提供了一种方便的途径去创建不同的网络请求方式,使用注解方式定义接口,方便我们配置参数;使用Retrofit,真正进行网络请求的还是OKHttp。

        Dargger2 和 DataBinding 我现在也不太熟。
      • ae14e5518257:为什么不说添加适配器直接返回Observable
        IAM四十二:@Joky_sss 唉,给忘掉了😂

      本文标题:我们真的需要使用RxJava+Retrofit吗?

      本文链接:https://www.haomeiwen.com/subject/wyphmttx.html