Android【Retrofit(HTTP客户端),RxJAVA(响应式编程)】

1 Retrofit(HTTP客户端)

1.1 简介

我们项目当中的每个 app 都需要用到网络和服务器进行交互,在 Android 项目开发中使用 HTTP 协议完成通信的话,基本上都要用到OkHttp 或者 Retrofit
OkHttp Retrofit 是目前应用最为广泛的网络组件。

1.2 Retrofit是什么?

准确来说, Retrofit 是一个 RESTful HTTP 网络请求框架的封装。
网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责网络请求接口的封装。 App 应用程序通过Retrofit请求网络,实际上是使用 Retrofit 接口层封装请求参数、 Header Url 等信息,之后由 OkHttp完成后续的请求操作。在服务端返回数据之后,OkHttp 将原始的结果交给 Retrofit Retrofit 根据用户的需求对结果进行解析。

1.3 Retrofit的使用 (异步GET)

第一步: 创建项目
第二步:导入依赖
implementation "com.github.bumptech.glide:glide:4.12.0"
    implementation("com.squareup.okhttp3:okhttp:4.10.0")
    implementation 'com.squareup.retrofit2:retrofit:2.4.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.0.2'
第三步:添加网络权限
<uses-permission android:name="android.permission.INTERNET"/>
第四步:在 activity_main.xml 添加 Recycle ,并给其设置 id
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/vp_head_img"
        android:layout_width="match_parent"
        android:layout_height="200dp"/>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_news"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="10dp"
        android:layout_below="@+id/vp_head_img"/>

</RelativeLayout>
第五步:创建子布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="150dp"
        android:layout_margin="5dp">


        <ImageView
            android:id="@+id/iv_news"
            android:layout_width="160dp"
            android:layout_height="match_parent"
            android:scaleType="fitXY" />

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="20dp"
            android:layout_toEndOf="@+id/iv_news"
            android:orientation="vertical">

            <TextView
                android:id="@+id/tv_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:layout_marginTop="30dp"
                android:text="text"/>

            <TextView
                android:id="@+id/tv_desc"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:layout_marginTop="30dp"
                android:text="text"/>

        </LinearLayout>



    </RelativeLayout>

</androidx.cardview.widget.CardView>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/iv_head"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:scaleType="fitXY"
        tools:srcCompat="@tools:sample/avatars" />

</RelativeLayout>
第六步:创建实体类
public class News {

    private boolean success;
    private String title;
    private String subtitle;
    private String update_time;
    private List<Data> data;

    public class Data {

        private int index;
        private String title;
        private String pic;
        private String desc;
        private String url;
        private String mobilUrl;
        public void setIndex(int index) {
            this.index = index;
        }
        public int getIndex() {
            return index;
        }

        public void setTitle(String title) {
            this.title = title;
        }
        public String getTitle() {
            return title;
        }

        public void setPic(String pic) {
            this.pic = pic;
        }
        public String getPic() {
            return pic;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }
        public String getDesc() {
            return desc;
        }

        public void setUrl(String url) {
            this.url = url;
        }
        public String getUrl() {
            return url;
        }

        public void setMobilUrl(String mobilUrl) {
            this.mobilUrl = mobilUrl;
        }
        public String getMobilUrl() {
            return mobilUrl;
        }

    }

    public News(List<Data> data) {

        this.data = data;
    }

    public List<Data> getData() {
        return data;
    }


    @Override
    public String toString() {
        return "News{" +
                "success=" + success +
                ", title='" + title + '\'' +
                ", subtitle='" + subtitle + '\'' +
                ", update_time='" + update_time + '\'' +
                ", data=" + data.toString() +
                '}';
    }

}
public class HeadImg {

    private boolean success;
    private String title;
    private String subtitle;
    private String update_time;
    private List<Data> data;

    public class Data {

        private int index;
        private String title;
        private String pic;
        private String desc;
        private String url;
        private String mobilUrl;
        public void setIndex(int index) {
            this.index = index;
        }
        public int getIndex() {
            return index;
        }

        public void setTitle(String title) {
            this.title = title;
        }
        public String getTitle() {
            return title;
        }

        public void setPic(String pic) {
            this.pic = pic;
        }
        public String getPic() {
            return pic;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }
        public String getDesc() {
            return desc;
        }

        public void setUrl(String url) {
            this.url = url;
        }
        public String getUrl() {
            return url;
        }

        public void setMobilUrl(String mobilUrl) {
            this.mobilUrl = mobilUrl;
        }
        public String getMobilUrl() {
            return mobilUrl;
        }

        @Override
        public String toString() {
            return "Data{" +
                    "index=" + index +
                    ", title='" + title + '\'' +
                    ", pic='" + pic + '\'' +
                    ", desc='" + desc + '\'' +
                    ", url='" + url + '\'' +
                    ", mobilUrl='" + mobilUrl + '\'' +
                    '}';
        }
    }

    public HeadImg(List<Data> data) {
        this.data = data;
    }

    public List<Data> getData() {
        return data;
    }

    @Override
    public String toString() {
        return "HeadImg{" +
                "data=" + data +
                '}';
    }
}
第七步:创建适配器
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHold> {

    private List<News.Data> list;

    public void setList(List<News.Data> list){
        this.list=list;
        notifyDataSetChanged();
    }

    @NonNull
    @Override
    public ViewHold onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.news_item, parent,false);
        ViewHold viewHold=new ViewHold(view);
        return viewHold;
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHold holder, int position) {
        News.Data data=list.get(position);

        holder.tv_tital.setText(data.getTitle());
        holder.tv_desc.setText(data.getDesc());
        Glide.with(holder.view).load(data.getPic()).into(holder.iv_news);

    }

    @Override
    public int getItemCount() {
        return list == null ? 0 : list.size();
    }

    public class ViewHold extends RecyclerView.ViewHolder{

        TextView tv_tital;
        TextView tv_desc;
        ImageView iv_news;

        View view;

        public ViewHold(@NonNull View itemView) {
            super(itemView);

            this.view=itemView;

            tv_tital=itemView.findViewById(R.id.tv_title);
            tv_desc=itemView.findViewById(R.id.tv_desc);
            iv_news=itemView.findViewById(R.id.iv_news);

        }
    }
}
public class HeadImgAdapter extends RecyclerView.Adapter<HeadImgAdapter.ViewHold> {

    private List<HeadImg.Data> list;

    public void setList(List<HeadImg.Data> list) {
        this.list = list;
        notifyDataSetChanged();
    }

    @NonNull
    @Override
    public ViewHold onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.head_img_item, parent, false);
        ViewHold viewHold=new ViewHold(view);
        return viewHold;
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHold holder, int position) {
        HeadImg.Data data = list.get(position);

        Glide.with(holder.view).load(data.getPic()).into(holder.iv_head);
    }

    @Override
    public int getItemCount() {
        return list == null ? 0 : list.size();
    }

    public class ViewHold extends RecyclerView.ViewHolder{

        ImageView iv_head;
        View view;

        public ViewHold(@NonNull View itemView) {
            super(itemView);

            this.view=itemView;
            iv_head=itemView.findViewById(R.id.iv_head);

        }
    }

}
第九步:创建请求接口
public interface GetRequest_Interface {

    //https://api.vvhan.com/api/hotlist?type=baiduRD
    @GET("api/hotlist?type=baiduRD")
    Call<News> getNews();


    //https://api.vvhan.com/api/hotlist?type=wxHot
    @GET("api/hotlist?type=wxHot")
    Call<HeadImg> getHeadImg();

}
第十步:进行网络请求
public class MainActivity extends AppCompatActivity {

    private ViewPager2 vp_head_img;
    private RecyclerView rv_news;

    private LinearLayoutManager layoutManager;

    private NewsAdapter newsAdapter;
    private HeadImgAdapter headImgadapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        vp_head_img=findViewById(R.id.vp_head_img);
        rv_news=findViewById(R.id.rv_news);

        layoutManager=new LinearLayoutManager(MainActivity.this);
        newsAdapter=new NewsAdapter();
        rv_news.setLayoutManager(layoutManager);
        rv_news.setAdapter(newsAdapter);

        headImgadapter=new HeadImgAdapter();
        vp_head_img.setAdapter(headImgadapter);

        loadNews();

        loadHeadImg();
    }

    private void loadNews() {

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://api.vvhan.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);

        Call<News> call = request.getNews();

        call.enqueue(new Callback<News>() {
            @Override
            public void onResponse(Call<News> call, Response<News> response) {
                newsAdapter.setList(response.body().getData());
            }

            @Override
            public void onFailure(Call<News> call, Throwable t) {
                Log.i("onFailure","连接失败");
            }
        });

    }

    private void loadHeadImg() {

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://api.vvhan.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);

        Call<HeadImg> call = request.getHeadImg();

        call.enqueue(new Callback<HeadImg>() {
            @Override
            public void onResponse(Call<HeadImg> call, Response<HeadImg> response) {
                headImgadapter.setList(response.body().getData());
                Log.i("onResponse","连接成功");
            }

            @Override
            public void onFailure(Call<HeadImg> call, Throwable t) {
                Log.i("onFailure","连接失败");
            }
        });

    }

}

2 RxJAVA(响应式编程)

2.1 简介

2.1.1 响应式编程

响应式编程的一个关键概念是事件。事件可以被等待,可以触发过程,也可以触发其它事件。事件是唯一的以合适的方式将我们的现实世界映射到我们的软件中:如果屋里太热了我们就打开一扇窗户。同样的,当我们的天气app 从服务端获取到新的天气数据后,我们需要更新 app 上展示天气信息的 UI ;汽车上的车道偏移系统探测到车辆偏移了正常路线就会提醒驾驶者纠正,就是是响应事件。

2.1.2 什么是RxJava

RxJava 是一种响应式编程,来创建基于事件的异步操作库。基于事件流的链式调用、逻辑清晰简
洁。
RxJava 我的理解是将事件从起点(上游)流向终点(下游),中间有很多卡片对数据进操作并传
递,每个卡片获取上一个卡片传递下来的结果然后对事件进行处理然后将结果传递给下一个卡片,
这样事件就从起点通过卡片一次次传递直到流向终点。

2.1.3 什么是观察者模式?

举个栗子, Android View 的点击监听器的实现, View 是被观察者, OnClickListener 对象是观察者,Activity要如何知道 View 被点击了?那就是派一个 OnClickListener 对象,入驻 View ,与 View 达成一个订阅关系,一旦View 被点击了,就通过 OnClickListener 对象的 OnClick 方法传达给 Activity 。采用观察者模式可以避免去轮询检查,节约有限的cpu 资源。

2.2 Retrofit+RxJava的使用

2.2.1 为什么要结合使用

代码简洁
借助 retorfit rxjava ,我们就不需要再做其他多余的封装或修改。网络请求写起来就会简单许多,而且结构也清晰。被观察者就是请求的发起,观察者就是请求的回调。
操作符的作用
rxjava 的优势就在于其操作符的使用,我理解的「操作符」就是 rxjava 为我们提供了一系列方法,可以运用在观察者模式中的「被观察者」「观察者」或「订阅过程」之间来控制。实际项目中我遇到过以下几种常见情况,可以用操作符来处理。
1. 请求结果需要做数据处理之后,再给页面展示。 「 map 」操作符,这个操作符就是在请求回来之后直接对数据做处理之后再返回给观察者。
2. 请求结果是做为下一个请求的请求入参。「 flatMap 」操作符,这个操作符是在遇到串联请求时使用的,当第一个请求返回结果之后,再拿着结果去请求下一个接口。

2.2.2 实现步骤

第一步: 创建项目
第二步:导入依赖
implementation "com.github.bumptech.glide:glide:4.12.0"
    //for rxjava
    implementation 'io.reactivex.rxjava2:rxjava:2.2.0'
    //for rxandroid
    implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
    //rxjava adapter for retrofit
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.0.2'
第三步:添加网络权限
<uses-permission android:name="android.permission.INTERNET"/>
第四步:在 activity_main.xml 添加 Recycle ,并给其设置 id
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >


    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/vp_head_img"
        android:layout_width="match_parent"
        android:layout_height="200dp"/>

</LinearLayout>
第五步:创建子布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/iv_head"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:scaleType="fitXY"
        tools:srcCompat="@tools:sample/avatars" />

</RelativeLayout>
第六步:创建实体类
public class HeadImg {

    private boolean success;
    private String title;
    private String subtitle;
    private String update_time;
    private List<Data> data;

    public class Data {

        private int index;
        private String title;
        private String pic;
        private String desc;
        private String url;
        private String mobilUrl;
        public void setIndex(int index) {
            this.index = index;
        }
        public int getIndex() {
            return index;
        }

        public void setTitle(String title) {
            this.title = title;
        }
        public String getTitle() {
            return title;
        }

        public void setPic(String pic) {
            this.pic = pic;
        }
        public String getPic() {
            return pic;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }
        public String getDesc() {
            return desc;
        }

        public void setUrl(String url) {
            this.url = url;
        }
        public String getUrl() {
            return url;
        }

        public void setMobilUrl(String mobilUrl) {
            this.mobilUrl = mobilUrl;
        }
        public String getMobilUrl() {
            return mobilUrl;
        }

        @Override
        public String toString() {
            return "Data{" +
                    "index=" + index +
                    ", title='" + title + '\'' +
                    ", pic='" + pic + '\'' +
                    ", desc='" + desc + '\'' +
                    ", url='" + url + '\'' +
                    ", mobilUrl='" + mobilUrl + '\'' +
                    '}';
        }
    }

    public HeadImg(List<Data> data) {
        this.data = data;
    }

    public List<Data> getData() {
        return data;
    }

    @Override
    public String toString() {
        return "HeadImg{" +
                "data=" + data +
                '}';
    }
}
第七步:创建适配器
public class HeadImgAdapter extends RecyclerView.Adapter<HeadImgAdapter.ViewHold> {

    private List<HeadImg.Data> list;

    public void setobservable(List<HeadImg.Data> list) {
        this.list = list;
        notifyDataSetChanged();
    }

    @NonNull
    @Override
    public ViewHold onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.head_img_item, parent, false);
        ViewHold viewHold=new ViewHold(view);
        return viewHold;
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHold holder, int position) {
        HeadImg.Data data = list.get(position);

        Glide.with(holder.view).load(data.getPic()).into(holder.iv_head);
    }

    @Override
    public int getItemCount() {
        return list == null ? 0 : list.size();
    }

    public class ViewHold extends RecyclerView.ViewHolder{

        ImageView iv_head;
        View view;

        public ViewHold(@NonNull View itemView) {
            super(itemView);

            this.view=itemView;
            iv_head=itemView.findViewById(R.id.iv_head);

        }
    }

}
第九步: 创建请求接口
public interface GetRequest_Interface {

    //https://api.vvhan.com/api/hotlist?type=wxHot
    @GET("api/hotlist?type=wxHot")
    Observable<HeadImg> getHeadImg();

}

第十步:进行网络请求

public class MainActivity extends AppCompatActivity {

    private ViewPager2 vp_head_img;

    private HeadImgAdapter headImgadapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        vp_head_img=findViewById(R.id.vp_head_img);

        headImgadapter=new HeadImgAdapter();
        vp_head_img.setAdapter(headImgadapter);

        loadHeadImg();

    }

    private void loadHeadImg() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://api.vvhan.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

        GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);

        Observable<HeadImg> observable = request.getHeadImg();

        observable.subscribeOn(Schedulers.io())//在io线程进行网络请求操作
                .observeOn(AndroidSchedulers.mainThread())//回到主线程 处理请求结果
                .subscribe(new Observer<HeadImg>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(HeadImg headImg) {
                        headImgadapter.setobservable(headImg.getData());
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.i("onError","连接失败");
                    }

                    @Override
                    public void onComplete() {
                        Log.i("onComplete","连接完成");
                    }
                });
    }

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值