实现订单列表页面
思路:
1. 实现如图1视图布局;
2. 实现订单列表功能;
3. 订单列表各元素绘制,严格按照如图所示效果设计;
4. 实现下拉刷新和上拉加载更多,分页功能
5. 列表视图用RecyclerView控件展示
接口:
uid=71
订单列表
https://www.zhaoapi.cn/product/getOrders
uid =71 & page=1
请求参数说明:
uid 用户id字段 String类型 必传
page 页码数 String类型 非必传(实现分页功能时,必传)
返回字段说明
status 订单状态 String类型
0:待支付
1:已支付
2:已取消
1.依赖
//《Retrofit网络请求依赖》 implementation 'com.squareup.retrofit2:retrofit:2.4.0' compile 'com.squareup.retrofit2:converter-gson:2.4.0' //《Recyclerview的依赖》 compile 'com.android.support:recyclerview-v7:26.1.0' //《Butterknife依赖(黄油刀)》 compile 'com.jakewharton:butterknife:8.8.1' annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' //《Rxjava2》 compile 'io.reactivex.rxjava2:rxjava:2.1.7' compile 'io.reactivex.rxjava2:rxandroid:2.0.1' //《RXjava2的适配器》 compile 'com.squareup.retrofit2:adapter-rxjava2:2.4.0' //SmartRefreshLayout依赖 compile 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0-alpha-5' compile 'com.scwang.smartrefresh:SmartRefreshHeader:1.1.0-alpha-5'//没有使用特殊Header,可以不加这行
2.权限
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
android:name=".app.App"
3.接口拼接
package com.example.dell.rikao0428.api; import com.example.dell.rikao0428.bean.MyDataBean; import io.reactivex.Flowable; import retrofit2.http.GET; import retrofit2.http.Query; public interface ApiService { //Flowable:背压 //拼接接口 @GET("product/getOrders") Flowable<MyDataBean> getData(@Query("uid")String uid,@Query("page")String page); }
4.接口拼接
package com.example.dell.rikao0428.utils; //接口拼接 public class StringUrl { //接口路径 public static final String BASE_URL="https://www.zhaoapi.cn/"; }
5.Retrofit网络请求封装
package com.example.dell.rikao0428.utils; import com.example.dell.rikao0428.api.ApiService; import retrofit2.Retrofit; import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; public class RetrofitUtils { //1创建一个单列模式 private static volatile RetrofitUtils instance; private final Retrofit retrofit; //2创建一个私有的无参构造 private RetrofitUtils(){ //创建Retrofit retrofit = new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create())//默认Gson进行解析 .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//使用RxJava2的适配器 .baseUrl(StringUrl.BASE_URL)//接口 .build(); } //4.创建一个静态方法,得到instance 判断是否为空 public static RetrofitUtils getInstance(){ if(null==instance){ synchronized (RetrofitUtils.class){ if(instance==null){ instance = new RetrofitUtils(); } } } //5返回创建的instance return instance; } //6创建方法 方便调用 public ApiService getApiService(){ return retrofit.create(ApiService.class); } }
6.SmartRefreshLayout的App
package com.example.dell.rikao0428.app; import android.app.Application; import android.content.Context; import com.example.dell.rikao0428.R; import com.scwang.smartrefresh.layout.SmartRefreshLayout; import com.scwang.smartrefresh.layout.api.DefaultRefreshFooterCreator; import com.scwang.smartrefresh.layout.api.DefaultRefreshHeaderCreator; import com.scwang.smartrefresh.layout.api.RefreshFooter; import com.scwang.smartrefresh.layout.api.RefreshHeader; import com.scwang.smartrefresh.layout.api.RefreshLayout; import com.scwang.smartrefresh.layout.footer.ClassicsFooter; import com.scwang.smartrefresh.layout.header.ClassicsHeader; //SmartRefreshLayout的App public class App extends Application{ //static 代码段可以防止内存泄露 static { //设置全局的Header构建器 SmartRefreshLayout.setDefaultRefreshHeaderCreator(new DefaultRefreshHeaderCreator() { @Override public RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) { layout.setPrimaryColorsId(R.color.colorPrimary, android.R.color.white);//全局设置主题颜色 return new ClassicsHeader(context);//.setTimeFormat(new DynamicTimeFormat("更新于 %s"));//指定为经典Header,默认是 贝塞尔雷达Header } }); //设置全局的Footer构建器 SmartRefreshLayout.setDefaultRefreshFooterCreator(new DefaultRefreshFooterCreator() { @Override public RefreshFooter createRefreshFooter(Context context, RefreshLayout layout) { //指定为经典Footer,默认是 BallPulseFooter return new ClassicsFooter(context).setDrawableSize(20); } }); } }
7.网络请求的数据Bean
package com.example.dell.rikao0428.bean; import java.util.List; public class MyDataBean { private String code; private String msg; private String page; private List<DataBean> data; public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public String getPage() { return page; } public void setPage(String page) { this.page = page; } public List<DataBean> getData() { return data; } public void setData(List<DataBean> data) { this.data = data; } public static class DataBean { private String createtime; private int orderid; private double price; private int status; private String title; private int uid; public String getCreatetime() { return createtime; } public void setCreatetime(String createtime) { this.createtime = createtime; } public int getOrderid() { return orderid; } public void setOrderid(int orderid) { this.orderid = orderid; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public int getUid() { return uid; } public void setUid(int uid) { this.uid = uid; } } }
8.M层接口
package com.example.dell.rikao0428.model; //M层接口 public interface DataModel { void getDataModel(String uid,String page); }
9.M层实现类
package com.example.dell.rikao0428.model; import com.example.dell.rikao0428.bean.MyDataBean; import com.example.dell.rikao0428.presenter.MyDataPresenter; import com.example.dell.rikao0428.utils.RetrofitUtils; import io.reactivex.Flowable; public class MyDataModel implements DataModel{ //创建构造器 将P层传给M层 MyDataPresenter presenter; public MyDataModel(MyDataPresenter presenter){ this.presenter=presenter; } @Override public void getDataModel(String uid,String page) { Flowable<MyDataBean> flowable = RetrofitUtils.getInstance().getApiService().getData(uid,page); //调用P层方法 将数据传给P层 presenter.Success(flowable); } }
10.P层接口
package com.example.dell.rikao0428.presenter; import com.example.dell.rikao0428.bean.MyDataBean; import io.reactivex.Flowable; //P层接口 public interface DataPresenter { //定义成功与失败的方法 void Success(Flowable<MyDataBean> flowable); void Error(); }11.P层实现类
package com.example.dell.rikao0428.presenter; import com.example.dell.rikao0428.bean.MyDataBean; import com.example.dell.rikao0428.model.MyDataModel; import com.example.dell.rikao0428.view.DataView; import java.util.List; import io.reactivex.Flowable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; import io.reactivex.subscribers.DefaultSubscriber; public class MyDataPresenter implements DataPresenter{ //创建构造器 将V层传给P层 DataView dataView; private final MyDataModel model; public MyDataPresenter(DataView dataView){ this.dataView=dataView; model = new MyDataModel(this); } //成功与失败的方法 @Override public void Success(Flowable<MyDataBean> flowable) { flowable.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new DefaultSubscriber<MyDataBean>() { @Override public void onNext(MyDataBean myDataBean) { List<MyDataBean.DataBean> list = myDataBean.getData(); if(list!=null){ //调用V层方法 将数据传给V层 dataView.toBackHome(list); } } @Override public void onError(Throwable t) { } @Override public void onComplete() { } }); } @Override public void Error() { } //调用接收uid的方法 public void getUid(String uid,String page){ model.getDataModel(uid,page); }
}
12.V层接口
package com.example.dell.rikao0428.view; import com.example.dell.rikao0428.bean.MyDataBean; import java.util.List; //V层接口 public interface DataView { //接收数据的方法 void toBackHome(List<MyDataBean.DataBean> list); }13.V层实现类
package com.example.dell.rikao0428.view; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.widget.Toast; import com.example.dell.rikao0428.R; import com.example.dell.rikao0428.adapter.MyAdapter; import com.example.dell.rikao0428.bean.MyDataBean; import com.example.dell.rikao0428.presenter.MyDataPresenter; import com.scwang.smartrefresh.layout.api.RefreshLayout; import com.scwang.smartrefresh.layout.listener.OnLoadMoreListener; import com.scwang.smartrefresh.layout.listener.OnRefreshListener; import java.util.ArrayList; import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; public class MainActivity extends AppCompatActivity implements DataView,MyAdapter.OnClickListener { @BindView(R.id.main_rcv) RecyclerView main_Rcv; private MyAdapter myAdapter; private String page = "1";//设置页数默认为0 List<MyDataBean.DataBean> list; List<MyDataBean.DataBean> AllList = new ArrayList<>();//设置大的集合 private int i = 0;//设置表示 用于判断上拉还是下拉 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); //设置布局管理器 main_Rcv.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false)); //实例化P层 final MyDataPresenter presenter = new MyDataPresenter(this); presenter.getUid("71",page); //设置监听事件 RefreshLayout refreshLayout = (RefreshLayout)findViewById(R.id.refreshLayout); //下拉刷新 refreshLayout.setOnRefreshListener(new OnRefreshListener() { @Override public void onRefresh(RefreshLayout refreshlayout) { i = 0;//状态值为0 page = "1";//页数为1 presenter.getUid("71",page);//调用P层请求方法 setAdapter();//调用适配器 refreshlayout.finishRefresh(2000/*,false*/);//传入false表示刷新失败 } }); //上拉加载 refreshLayout.setOnLoadMoreListener(new OnLoadMoreListener() { @Override public void onLoadMore(RefreshLayout refreshlayout) { i = 1;//状态值为1 page= (Integer.valueOf(page)+1)+"";//页数每次加1 现在先转为int类型+1,再转为String类型 presenter.getUid("71",page);//调用P层请求方法 setAdapter();//调用适配器 refreshlayout.finishLoadMore(2000/*,false*/);//传入false表示加载失败 } }); } //接收数据 @Override public void toBackHome(List<MyDataBean.DataBean> list) { //判断状态值为时(下拉) if(i == 0){ //清除原本集合中的全部数据 AllList.clear(); } //判断值不为0时,则为1(上拉) 将得到的集合全部添加到大集合中 AllList.addAll(list); //调用适配器 setAdapter(); } //创建适配器 public void setAdapter(){ //判断适配器是否为空 if(myAdapter==null){ //为空则创建 myAdapter = new MyAdapter(this, AllList); //赋值给RecyclerView main_Rcv.setAdapter(myAdapter); }else{ //不为空则刷新即可 myAdapter.notifyDataSetChanged(); } //调用适配器中的监听事件 myAdapter.OnClick(this); } //重写适配器中的监听事件 @Override public void OnChaClick(int position) { Toast.makeText(this,"查看了订单",Toast.LENGTH_SHORT).show(); } }14.适配器
package com.example.dell.rikao0428.adapter; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import com.example.dell.rikao0428.R; import com.example.dell.rikao0428.bean.MyDataBean; import java.util.List; public class MyAdapter extends RecyclerView.Adapter{ Context context; List<MyDataBean.DataBean> list; public MyAdapter(Context context, List<MyDataBean.DataBean> list) { this.context=context; this.list=list; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //引入子布局 View view = View.inflate(context, R.layout.rcv_item, null); //创建MyViewHolder 将View传过去 MyViewHolder myViewHolder = new MyViewHolder(view); return myViewHolder; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { MyViewHolder myViewHolder = (MyViewHolder) holder; //为控件赋值 myViewHolder.rcv_title.setText(list.get(position).getTitle()); myViewHolder.rcv_price.setText("价格:"+list.get(position).getPrice()); myViewHolder.rcv_data.setText("创建时间:"+list.get(position).getCreatetime()); //得到集合中的状态值 int i = list.get(position).getStatus(); //进行判断 并赋值 if(i==0){ myViewHolder.rcv_zt.setText("待支付"); myViewHolder.rcv_dd.setText("取消订单"); }else if(i==1){ myViewHolder.rcv_zt.setText("已支付"); myViewHolder.rcv_dd.setText("查看订单"); }else{ myViewHolder.rcv_zt.setText("已取消"); myViewHolder.rcv_dd.setText("查看订单"); } //给查看订单设置点击事件 myViewHolder.rcv_dd.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //点击事件 onClickListener.OnChaClick(position); } }); } //集合的条目数量 @Override public int getItemCount() { return list.size(); } //创建MyViewHolder class MyViewHolder extends RecyclerView.ViewHolder{ private final TextView rcv_title; private final TextView rcv_price; private final TextView rcv_zt; private final TextView rcv_data; private final Button rcv_dd; public MyViewHolder(View view) { super(view); //找到布局文件的控件的ID rcv_title = view.findViewById(R.id.rcv_title); rcv_price = view.findViewById(R.id.rcv_price); rcv_zt = view.findViewById(R.id.rcv_zt); rcv_data = view.findViewById(R.id.rcv_data); rcv_dd = view.findViewById(R.id.rcv_dd); } } //创建暴露点击事件的类 OnClickListener onClickListener; public void OnClick(OnClickListener onClickListener){ this.onClickListener=onClickListener; } //创建点击事件接口 public interface OnClickListener{ void OnChaClick(int position); } }15.主布局
<?xml version="1.0" encoding="utf-8"?> <!--设置SmartRefreshLayout为最大的控件 子控件只能有三个--> <com.scwang.smartrefresh.layout.SmartRefreshLayout 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:id="@+id/refreshLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.dell.rikao0428.view.MainActivity"> <!--头部布局--> <com.scwang.smartrefresh.layout.header.ClassicsHeader android:layout_width="match_parent" android:layout_height="wrap_content"/> <!--RecyclerView--> <android.support.v7.widget.RecyclerView android:id="@+id/main_rcv" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v7.widget.RecyclerView> <!--底部布局--> <com.scwang.smartrefresh.layout.footer.ClassicsFooter android:layout_width="match_parent" android:layout_height="wrap_content"/> </com.scwang.smartrefresh.layout.SmartRefreshLayout>16.子条目布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="10dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="50dp"> <TextView android:id="@+id/rcv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="订单标题测试" android:layout_centerVertical="true"/> <TextView android:id="@+id/rcv_zt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="待支付" android:layout_alignParentRight="true" android:layout_centerVertical="true"/> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="50dp"> <TextView android:id="@+id/rcv_price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#f00" android:text="价格:99.99" android:layout_centerVertical="true"/> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="50dp"> <TextView android:id="@+id/rcv_data" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="创建时间:2017-11-09T09:20:58" android:layout_centerVertical="true"/> <Button android:id="@+id/rcv_dd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="查看订单" android:layout_alignParentRight="true" android:layout_centerVertical="true"/> </RelativeLayout> </LinearLayout>