商品分类接口
https://www.zhaoapi.cn/product/getProducts?pscid=1
请求参数:
pscid商品id字段 String类型 必传
返回数据:
见json字符串注册接口
1. 新建Android Studio项目,实现商品分类列表效果
2. 严格实现上图布局效果,屏幕适配页面美观
3. 使用MVP分包明确 避免内存泄漏
4 使用Fresco获取图片 图片路径需截取
5. 使用Retrofit请求商品分类接口
1) Retrofit加载网络数据 添加动态代理
2) RxJava异步处理数据 泛型封装对象
3) 将请求回来的数据使用recyclerview展示
1.依赖
//《Retrofit网络请求依赖》
implementation 'com.squareup.retrofit2:retrofit:2.4.0' compile 'com.squareup.retrofit2:converter-gson:2.4.0' // compile 'com.squareup.retrofit2:retrofit:2.3.0' //《Gson解析依赖》 compile 'com.google.code.gson:gson:2.2.4' //《Fresco图片框架依赖》 compile 'com.facebook.fresco:fresco:0.14.1' //《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 'com.squareup.retrofit2:adapter-rxjava2:2.4.0' //《Rxjava2》 compile 'io.reactivex.rxjava2:rxjava:2.1.7' compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
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"/>
3.ApiService拼接接口
package com.example.dell.a1511r0418.api; import com.example.dell.a1511r0418.model.MessageBean; import com.example.dell.a1511r0418.model.MyDataBean; import java.util.List; import io.reactivex.Flowable; import retrofit2.http.GET; import retrofit2.http.Query; public interface ApiService { //Flowable:背压 //拼接接口 @GET("product/getProducts") Flowable>> getData(@Query("pscid")String pscid); }
4.初始化Fresco 设置使用默认设置加载图片
package com.example.dell.a1511r0418.app; import android.app.Application; import com.facebook.drawee.backends.pipeline.Fresco; public class App extends Application{ @Override public void onCreate() { super.onCreate(); //初始化Fresco 设置使用默认设置加载图片 Fresco.initialize(this); } }
5.Retrofit 网络请求框架
package com.example.dell.a1511r0418.utils; import com.example.dell.a1511r0418.api.ApiService; import retrofit2.Retrofit; import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; //Retrofit 网络请求框架 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.接口拼接
package com.example.dell.a1511r0418.utils; public class StringUrl { //接口路径 public static final String BASE_URL="https://www.zhaoapi.cn/"; }
7.接口网络获取数据的外层封装
package com.example.dell.a1511r0418.model; //泛型封装 public class MessageBean<T> { private String msg; private String code; private String page; private T data; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getPage() { return page; } public void setPage(String page) { this.page = page; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
8.接口网络获取数据的内层封装
package com.example.dell.a1511r0418.model; public class MyDataBean { private double bargainPrice; private String createtime; private String detailUrl; private String images; private int itemtype; private int pid; private double price; private int pscid; private int salenum; private int sellerid; private String subhead; private String title; public double getBargainPrice() { return bargainPrice; } public void setBargainPrice(double bargainPrice) { this.bargainPrice = bargainPrice; } public String getCreatetime() { return createtime; } public void setCreatetime(String createtime) { this.createtime = createtime; } public String getDetailUrl() { return detailUrl; } public void setDetailUrl(String detailUrl) { this.detailUrl = detailUrl; } public String getImages() { return images; } public void setImages(String images) { this.images = images; } public int getItemtype() { return itemtype; } public void setItemtype(int itemtype) { this.itemtype = itemtype; } public int getPid() { return pid; } public void setPid(int pid) { this.pid = pid; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public int getPscid() { return pscid; } public void setPscid(int pscid) { this.pscid = pscid; } public int getSalenum() { return salenum; } public void setSalenum(int salenum) { this.salenum = salenum; } public int getSellerid() { return sellerid; } public void setSellerid(int sellerid) { this.sellerid = sellerid; } public String getSubhead() { return subhead; } public void setSubhead(String subhead) { this.subhead = subhead; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } }
9.M层接口
package com.example.dell.a1511r0418.model; public interface DataModel { //请求数据的方法 void getModelData(String pscid); }
10.M层接口实现类
package com.example.dell.a1511r0418.model; import com.example.dell.a1511r0418.present.MyDataPresent; import com.example.dell.a1511r0418.utils.RetrofitUtils; import java.util.List; import io.reactivex.Flowable; public class MyDataModel implements DataModel{ //创建构建器 将P层传入M层 MyDataPresent present; public MyDataModel(MyDataPresent present){ this.present=present; } //请求数据的方法 @Override public void getModelData(String pscid) { Flowable>> flowable = RetrofitUtils.getInstance().getApiService().getData(pscid); //调用P层方法,将数据传给P层 present.getBean(flowable); } }
11.P层接口
package com.example.dell.a1511r0418.present; public interface DataPresent { //调用请求的方法 void getsjData(String pscid); }
12.P层接口实现类
package com.example.dell.a1511r0418.present; import com.example.dell.a1511r0418.model.MessageBean; import com.example.dell.a1511r0418.model.MyDataBean; import com.example.dell.a1511r0418.model.MyDataModel; import com.example.dell.a1511r0418.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.DisposableSubscriber; public class MyDataPresent implements DataPresent { private DisposableSubscriber subscriber; //创建方法 将V层传入P层 DataView dataView; public MyDataModel myDataModel; public void attachView(DataView dataView) { this.dataView = dataView; } //防止泄露 public void detachView() { if (dataView != null) { dataView = null; } if (!subscriber.isDisposed()){ subscriber.dispose(); } } //创建请求的方法 @Override public void getsjData(String pscid) { //实例化M层 将P层传给M层 myDataModel = new MyDataModel(this); //调用M层方法 将pscid传给M层 myDataModel.getModelData(pscid); } //获取请求后数据 public void getBean(Flowable>> flowable) { //转换线程 flowable.subscribeOn(Schedulers.io())//Io线程 网络请求 .observeOn(AndroidSchedulers.mainThread())//主线程 更新Ui .subscribeWith(new DisposableSubscriber >>() { //下一个 @Override public void onNext(MessageBean > listMessageBean) { //判断返回的数据是否为空 if(listMessageBean!=null){ List
list = listMessageBean.getData(); //不为空则将数据传给V层 if(list!=null){ dataView.Success(list); } } } //异常 传给V层 @Override public void onError(Throwable t) { dataView.Eroor(t); } //成功 @Override public void onComplete() {} }); } }
13.V层接口
package com.example.dell.a1511r0418.view; public interface DataView { //成功和失败的方法 void Success(Object o); void Eroor(Throwable t); }14.V层接口实现类
package com.example.dell.a1511r0418.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.util.Log; import com.example.dell.a1511r0418.R; import com.example.dell.a1511r0418.adapter.MyAdaptr; import com.example.dell.a1511r0418.model.MyDataBean; import com.example.dell.a1511r0418.present.MyDataPresent; import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; public class MainActivity extends AppCompatActivity implements DataView { @BindView(R.id.mian_rcv) RecyclerView mian_Rcv; private MyDataPresent myDataPresent; private MyAdaptr myAdaptr; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); //设置布局 mian_Rcv.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false)); //实例化P层 myDataPresent = new MyDataPresent(); //调用P层方法 将pscid传给P层 myDataPresent.getsjData("1"); //调用P层方法 将V层传给P层 myDataPresent.attachView(this); } //成功 @Override public void Success(Object o) { //因参数是Object 所有需要转成自己数据的类型 Listlist = (List ) o; Log.e("+++++", "Success: "+list.size()); //创建适配器 myAdaptr = new MyAdaptr(this,list); //RecyclerView调用适配器 mian_Rcv.setAdapter(myAdaptr); } //失败 @Override public void Eroor(Throwable t) { Log.e("======", "Eroor: "+t.getMessage() ); } //当Activity销毁时 需将V层置空 防止内存泄露 @Override protected void onDestroy() { super.onDestroy(); if (myDataPresent!=null){ myDataPresent.detachView(); } } }
15.适配器
package com.example.dell.a1511r0418.adapter; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.example.dell.a1511r0418.R; import com.example.dell.a1511r0418.model.MyDataBean; import com.facebook.drawee.view.SimpleDraweeView; import java.util.List; public class MyAdaptr extends RecyclerView.Adapter{ Context context; Listlist; public MyAdaptr(Context context, List 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, int position) { MyViewHolder myViewHolder = (MyViewHolder) holder; //图片需截取 先用其中url一个代替 //String imhurl="https://m.360buyimg.com/n0/jfs/t9004/210/1160833155/647627/ad6be059/59b4f4e1N9a2b1532.jpg!q70.jpg"; //切割图片路径 String imhurl=""; String images = list.get(position).getImages(); String[] split = images.split("\\|"); for (int i = 0;i length;i++){ imhurl=split[i]; } //为控件进行赋值 myViewHolder.rcv_img.setImageURI(imhurl); myViewHolder.rcv_title.setText(list.get(position).getTitle()); myViewHolder.rcv_price.setText("¥"+list.get(position).getPrice()); } //条目数量 @Override public int getItemCount() { return list.size(); } class MyViewHolder extends RecyclerView.ViewHolder{ private final SimpleDraweeView rcv_img; private final TextView rcv_title; private final TextView rcv_price; public MyViewHolder(View view) { super(view); //找到布局文件的控件的ID rcv_img = view.findViewById(R.id.rcv_img); rcv_title = view.findViewById(R.id.rcv_title); rcv_price = view.findViewById(R.id.rcv_price); } } }
16.主布局文件
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" android:orientation="vertical" tools:context="com.example.dell.a1511r0418.view.MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/mian_rcv" android:layout_width="match_parent" android:layout_height="match_parent"> android.support.v7.widget.RecyclerView>
LinearLayout>
17.条目布局
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"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="10px"> <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/rcv_img" android:layout_width="150px" android:layout_height="150px" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="10px"> <TextView android:id="@+id/rcv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="每个中秋都不能简单" android:padding="10px"/> <TextView android:id="@+id/rcv_price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="10px" android:text="¥99.99"/> LinearLayout> LinearLayout> LinearLayout>