RetrofitUtils工具类
public class RetrofitUtils {private static RetrofitUtils retrofitUtils;private Retrofit retrofit;private RetrofitUtils(){OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)).build();//第一步retrofit = new Retrofit.Builder().baseUrl(Api.BASE_URL).client(okHttpClient)//关联okhttp的//工厂模式,java有23种.addConverterFactory(GsonConverterFactory.create())//数据转换器.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//rxjava的请求回调适配器.build();}public static RetrofitUtils getInstance() {if (retrofitUtils==null){synchronized (RetrofitUtils.class){if (retrofitUtils==null){retrofitUtils = new RetrofitUtils();}}}return retrofitUtils;}/*** 动态获取接口管理类对象* @param tClass* @param <T>* @return*/public <T>T createservice(Class<T> tClass){// IHomeApiService iHomeApiService = retrofit.create(IHomeApiService.class);T t = retrofit.create(tClass);return t;}/*** 判断是否有网* @return*/public boolean isNet(){return NetworkUtils.isConnected();}}
MVP框架请求数据
model层
public class ClsModel implements ClzContract.IModel {@Overridepublic void getLeftData(final ModelCallback modelCallback) {// Observable observable = null;//被观察者// Observer observer = null;//观察者// observable.subscribe(observer);RetrofitUtils.getInstance().createservice(ClsApiservice.class).getCls()//获取rxjava的被观察者,observable对象.subscribeOn(Schedulers.io())//指定obserable被观察者所在线程(请求网络的线程).observeOn(AndroidSchedulers.mainThread())//指定observer观察者所在线程(响应后的数据所在的线程,onnext方法运行的线程).subscribe(new Observer<ClsEntity>() {//订阅关系/*** 是否订阅成功* @param d*/@Overridepublic void onSubscribe(Disposable d) {}/*** 接收成功* @param value*/@Overridepublic void onNext(ClsEntity value) {modelCallback.success(value);}/*** 失败* @param e*/@Overridepublic void onError(Throwable e) {modelCallback.failure(e);}/*** 接收完成*/@Overridepublic void onComplete() {}});}@Overridepublic void getRightData(HashMap<String, String> params, final ModelCallback modelCallback) {RetrofitUtils.getInstance().createservice(ClsApiservice.class).getRight(params).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<RightEntity>() {@Overridepublic void onSubscribe(Disposable d) {}@Overridepublic void onNext(RightEntity rightEntity) {modelCallback.success(rightEntity);}@Overridepublic void onError(Throwable e) {modelCallback.failure(e);}@Overridepublic void onComplete() {}});}}
presenter层
public class ClsPresenter implements ClzContract.IPresenter {private ClzContract.IView iView;private ClsModel clsModel;public ClsPresenter(ClzContract.IView iView) {this.iView = iView;this.clsModel = new ClsModel();}@Overridepublic void getLeftData() {clsModel.getLeftData(new ClzContract.IModel.ModelCallback() {@Overridepublic void success(Object o) {iView.success(o);}@Overridepublic void failure(Throwable throwable) {iView.failure(throwable);}});}@Overridepublic void getRightData(HashMap<String, String> params) {clsModel.getRightData(params, new ClzContract.IModel.ModelCallback() {@Overridepublic void success(Object o) {iView.success(o);}@Overridepublic void failure(Throwable throwable) {iView.failure(throwable);}});}}
ApiService Greendao用法
public interface ClsApiservice {//io包下的Observable@GET(\"small/commodity/v1/findCategory\")Observable<ClsEntity> getCls();//io包下的Observable@GET(\"small/commodity/v1/findCommodityByCategory\")Observable<RightEntity> getRight(@QueryMap HashMap<String,String> params);}
对应的Entity
自动生成
@Entitypublic class GreendaoEntity {@Id(autoincrement = true)private Long id;private String json;private String key;//key区分哪个json的@Generated(hash = 1063073890)public GreendaoEntity(Long id, String json, String key) {this.id = id;this.json = json;this.key = key;}@Generated(hash = 393499003)public GreendaoEntity() {}public Long getId() {return this.id;}public void setId(Long id) {this.id = id;}public String getJson() {return this.json;}public void setJson(String json) {this.json = json;}public String getKey() {return this.key;}public void setKey(String key) {this.key = key;}}
Api定义接口
public class Api {public static final String BASE_URL = \"http://172.17.8.100/\";//必须以/结束,不能少public static final String HOME_URL = \"small/commodity/v1/commodityList\";}
封装对象Entity
左边
public class ClsEntity {public String message;public String status;public List<Cls> result;public static class Cls{public String id;public String name;public List<Category> secondCategoryVo;public static class Category{public String id;public String name;}}}
右边
public class RightEntity {public String message;public String status;public List<Right> result;public static class Right{public String commodityId;public String commodityName;public String masterPic;public String price;public String saleNum;}}
契约类
public interface ClzContract {interface IModel{//左侧分类void getLeftData(ModelCallback modelCallback);//根据二级分类查询之下的商品void getRightData(HashMap<String,String> params, ModelCallback modelCallback);interface ModelCallback{void success(Object o);void failure(Throwable throwable);}}interface IView{void success(Object o);void failure(Throwable throwable);}interface IPresenter{//左侧分类void getLeftData();//根据二级分类查询之下的商品void getRightData(HashMap<String,String> params);}}
主页面
public class ClsActivity extends AppCompatActivity implements ClzContract.IView {DaoMaster.DevOpenHelper helper;private RecyclerView leftRv;private RecyclerView rightRv;private ClsPresenter clsPresenter;private SQLiteDatabase sqLiteDatabase;private DaoMaster daoMaster;private DaoSession daoSession;private DaoMaster.DevOpenHelper helper1;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_cls);clsPresenter = new ClsPresenter(this);leftRv = findViewById(R.id.rv_left);rightRv = findViewById(R.id.rv_right);leftRv.setLayoutManager(new LinearLayoutManager(this));rightRv.setLayoutManager(new GridLayoutManager(this,2));//注册eventbusEventBus.getDefault().register(this);//数据库帮助类,创建数据库,以clsdb名字helper1 = new DaoMaster.DevOpenHelper(this,\"clsdb\");//创建数据库的读写工具类sqLiteDatabase = helper1.getWritableDatabase();//创建daomaster对象daoMaster = new DaoMaster(sqLiteDatabase);//创建daosesiiondaoSession = daoMaster.newSession();if (RetrofitUtils.getInstance().isNet()){//伪代码,网络判断clsPresenter.getLeftData();}else{List<GreendaoEntity> greendaoEntities = daoSession.getGreendaoEntityDao().loadAll();if (greendaoEntities!=null&&greendaoEntities.size()>0){GreendaoEntity greendaoEntity = greendaoEntities.get(0);//第0条数据String json = greendaoEntity.getJson();ClsEntity clsEntity = new Gson().fromJson(json,ClsEntity.class);//只获取一级数据下的二级列表数据LeftAdapter leftAdapter = new LeftAdapter(this,clsEntity.result.get(0).secondCategoryVo);leftRv.setAdapter(leftAdapter);//接口回调的实现,得到值了leftAdapter.setLeftClick(new LeftAdapter.LeftClick() {@Overridepublic void leftItemClick(String id) {//发送EventBus.getDefault().post(id);}});}}}@Overridepublic void success(Object o) {//请求左侧分类的json串串if (o instanceof ClsEntity){ClsEntity clsEntity = (ClsEntity) o;//只获取一级数据下的二级列表数据LeftAdapter leftAdapter = new LeftAdapter(this,clsEntity.result.get(0).secondCategoryVo);leftRv.setAdapter(leftAdapter);//接口回调的实现,得到值了leftAdapter.setLeftClick(new LeftAdapter.LeftClick() {@Overridepublic void leftItemClick(String id) {//发送EventBus.getDefault().post(id);}});//缓存数据GreendaoEntity greendaoEntity = new GreendaoEntity();String json = new Gson().toJson(clsEntity);greendaoEntity.setJson(json);greendaoEntity.setKey(\"分类\");daoSession.getGreendaoEntityDao().insert(greendaoEntity);}else if (o instanceof RightEntity){RightEntity rightEntity = (RightEntity) o;RightAdapter rightAdapter = new RightAdapter(this,rightEntity.result);rightRv.setAdapter(rightAdapter);}}/*** 接收二级类目的id* @param id*/@Subscribe(threadMode = ThreadMode.MAIN)public void getId(String id){HashMap<String,String> params = new HashMap<>();params.put(\"categoryId\",id);params.put(\"page\",\"1\");params.put(\"count\",\"10\");clsPresenter.getRightData(params);}@Overridepublic void failure(Throwable throwable) {}@Overrideprotected void onDestroy() {super.onDestroy();EventBus.getDefault().unregister(this);}}
适配器
左边
public class LeftAdapter extends RecyclerView.Adapter<LeftAdapter.MyViewHolder> {private Context context;private List<ClsEntity.Cls.Category> categoryList;public LeftAdapter(Context context, List<ClsEntity.Cls.Category> categoryList) {this.context = context;this.categoryList = categoryList;}@NonNull@Overridepublic MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = View.inflate(context, R.layout.left_item_layout,null);MyViewHolder myViewHolder = new MyViewHolder(view);return myViewHolder;}@Overridepublic void onBindViewHolder(@NonNull MyViewHolder holder, final int position) {holder.tv.setText(categoryList.get(position).name);holder.itemView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {leftClick.leftItemClick(categoryList.get(position).id);}});}@Overridepublic int getItemCount() {return categoryList.size();}class MyViewHolder extends RecyclerView.ViewHolder{private TextView tv;public MyViewHolder(@NonNull View itemView) {super(itemView);tv = itemView.findViewById(R.id.tv);}}private LeftClick leftClick;public void setLeftClick(LeftClick leftClick) {this.leftClick = leftClick;}public interface LeftClick{void leftItemClick(String id);}}
右边
public class RightAdapter extends RecyclerView.Adapter<RightAdapter.MyViewHolder> {private Context context;private List<RightEntity.Right> list;public RightAdapter(Context context, List<RightEntity.Right> list) {this.context = context;this.list = list;}@NonNull@Overridepublic MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = View.inflate(context, R.layout.right_item_layout,null);MyViewHolder myViewHolder = new MyViewHolder(view);return myViewHolder;}@Overridepublic void onBindViewHolder(@NonNull MyViewHolder holder, final int position) {holder.tv.setText(list.get(position).commodityName);Glide.with(context).load(list.get(position).masterPic).placeholder(R.mipmap.ic_launcher).error(R.mipmap.ic_launcher).into(holder.iv);}@Overridepublic int getItemCount() {return list.size();}class MyViewHolder extends RecyclerView.ViewHolder{private TextView tv;private ImageView iv;public MyViewHolder(@NonNull View itemView) {super(itemView);tv = itemView.findViewById(R.id.tv);iv = itemView.findViewById(R.id.iv);}}}
主页面对应布局
<?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=\"horizontal\"tools:context=\".ClsActivity\"><androidx.recyclerview.widget.RecyclerViewandroid:id=\"@+id/rv_left\"android:layout_width=\"0dp\"android:layout_weight=\"1\"android:layout_height=\"match_parent\"/><androidx.recyclerview.widget.RecyclerViewandroid:id=\"@+id/rv_right\"android:layout_width=\"0dp\"android:layout_weight=\"2\"android:layout_height=\"match_parent\"/></LinearLayout>
左列表对应布局
<?xml version=\"1.0\" encoding=\"utf-8\"?><LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"android:orientation=\"vertical\" android:layout_width=\"match_parent\"android:layout_height=\"wrap_content\"><TextViewandroid:id=\"@+id/tv\"android:padding=\"10dp\"android:layout_width=\"wrap_content\"android:layout_height=\"wrap_content\"/></LinearLayout>
右列表对应的布局
<?xml version=\"1.0\" encoding=\"utf-8\"?><LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"android:orientation=\"vertical\" android:layout_width=\"match_parent\"android:layout_height=\"wrap_content\"><ImageViewandroid:id=\"@+id/iv\"android:src=\"@mipmap/ic_launcher\"android:layout_width=\"80dp\"android:layout_gravity=\"center\"android:scaleType=\"centerCrop\"android:layout_height=\"80dp\"/><TextViewandroid:id=\"@+id/tv\"android:text=\"标题\"android:singleLine=\"true\"android:layout_gravity=\"center\"android:layout_width=\"wrap_content\"android:layout_height=\"wrap_content\"/></LinearLayout>
build.gradle项目里面用的依赖文件
apply plugin: \'com.android.application\'apply plugin: \'org.greenrobot.greendao\'android {compileSdkVersion 28buildToolsVersion \"29.0.2\"defaultConfig {applicationId \"com.sss.demo\"minSdkVersion 15targetSdkVersion 28versionCode 1versionName \"1.0\"testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile(\'proguard-android-optimize.txt\'), \'proguard-rules.pro\'}}}greendao {schemaVersion 1//自己的路径daoPackage \'com.sss.demo.greendao\'targetGenDir \'src/main/java\'}dependencies {implementation fileTree(dir: \'libs\', include: [\'*.jar\'])implementation \'androidx.appcompat:appcompat:1.1.0\'implementation \'androidx.constraintlayout:constraintlayout:1.1.3\'testImplementation \'junit:junit:4.12\'androidTestImplementation \'androidx.test.ext:junit:1.1.1\'androidTestImplementation \'androidx.test.espresso:espresso-core:3.2.0\'//retrofit核心库implementation \'com.squareup.retrofit2:retrofit:2.6.2\'//retrofit辅助,gson解析的库implementation \'com.squareup.retrofit2:converter-gson:2.6.2\'implementation \'com.squareup.retrofit2:adapter-rxjava2:2.6.2\' // 必要依赖,和Rxjava结合必须用到,下面会提到implementation \'io.reactivex.rxjava2:rxandroid:2.1.1\'//切换到主线程的依赖//okhttp日志拦截器implementation \'com.squareup.okhttp3:logging-interceptor:4.2.2\'//recycerviewimplementation \'androidx.recyclerview:recyclerview:1.1.0\'//eventbus 事件总线,传值implementation \'org.greenrobot:eventbus:3.1.1\'//图片加载框架implementation \'com.github.bumptech.glide:glide:4.10.0\'//greendao 数据存储orm框架implementation \'org.greenrobot:greendao:3.2.2\' // add library// if u use AndroidX, use the following,网络判断工具类implementation \'com.blankj:utilcodex:1.26.0\'}
工程下的build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.buildscript {repositories {google()jcenter()mavenCentral()}dependencies {classpath \'com.android.tools.build:gradle:3.5.2\'classpath \'org.greenrobot:greendao-gradle-plugin:3.2.2\'// NOTE: Do not place your application dependencies here; they belong// in the individual module build.gradle files}}allprojects {repositories {google()jcenter()mavenCentral()}}task clean(type: Delete) {delete rootProject.buildDir}