仿京东分类MVP

这里写图片描述

依赖

implementation ‘io.reactivex.rxjava2:rxandroid:2.0.2’
implementation ‘io.reactivex.rxjava2:rxjava:2.1.12’
implementation ‘com.jakewharton:butterknife:8.8.1’
implementation ‘com.jakewharton.rxbinding2:rxbinding:2.1.1’
implementation ‘com.squareup.okhttp3:logging-interceptor:3.10.0’
implementation ‘com.squareup.retrofit2:retrofit:2.4.0’
compile ‘com.squareup.retrofit2:converter-gson:2.4.0’
compile ‘com.squareup.retrofit2:adapter-rxjava2:2.4.0’
implementation ‘com.github.bumptech.glide:glide:4.7.1’
annotationProcessor ‘com.github.bumptech.glide:compiler:4.7.1’
implementation ‘org.greenrobot:greendao:3.2.2’
compile ‘org.greenrobot:eventbus:3.1.1’
annotationProcessor ‘com.jakewharton:butterknife-compiler:8.8.1’
implementation ‘com.android.support:recyclerview-v7:26.+’

权限

 <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" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

布局

activity_main.xml

<?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="horizontal">


    <fragment
        android:id="@+id/fragment_left"
        android:name="com.bwie.complexdemo.view.LeftFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3" />

    <fragment
        android:id="@+id/fragment_right"
        android:name="com.bwie.complexdemo.view.RightFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="7" />

</LinearLayout>

fragment_left.xml

<?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.support.v7.widget.RecyclerView
        android:id="@+id/rv_left"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"></android.support.v7.widget.RecyclerView>

</LinearLayout>

fragment_right.xml

<?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.support.v7.widget.RecyclerView
        android:id="@+id/rv_right"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"></android.support.v7.widget.RecyclerView>

</LinearLayout>

item_left_list.xml

<?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="wrap_content"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/img_left_item"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_gravity="center_horizontal" />

    <TextView
        android:id="@+id/txt_left_item"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal" />

</LinearLayout>

item_right_first.xml

<?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="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/txt_right_first"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_second_right"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"></android.support.v7.widget.RecyclerView>

</LinearLayout>

item_right_second.xml

<?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="wrap_content"
    android:orientation="vertical"
    android:padding="10dp">

    <ImageView
        android:id="@+id/img_right_second_item"
        android:layout_width="45dp"
        android:layout_height="45dp"
        android:layout_gravity="center_horizontal" />

    <TextView
        android:id="@+id/txt_right_second_item"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal" />

</LinearLayout>

adapter

LeftListAdapter.java

package com.bwie.complexdemo.adapter;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.bwie.complexdemo.R;
import com.bwie.complexdemo.entity.LeftCategory;
import com.bwie.complexdemo.inter.OnRecyclerViewItemClickListener;

import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;

/**
 * Created by eric on 2018/4/18.
 */

public class LeftListAdapter extends RecyclerView.Adapter<LeftListAdapter.ViewHolder> {
    private Context context;
    private List<LeftCategory> list;

    private OnRecyclerViewItemClickListener listener;

    public void setListener(OnRecyclerViewItemClickListener listener) {
        this.listener = listener;
    }

    public LeftListAdapter(Context context, List<LeftCategory> list) {
        this.context = context;
        this.list = list;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = View.inflate(context, R.layout.item_left_list, null);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
        Glide.with(context).load(list.get(position).getIcon()).into(holder.imgLogo);
        holder.txtTitle.setText(list.get(position).getName());
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                listener.onItemClick(position);
            }
        });
    }

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

    class ViewHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.img_left_item)
        ImageView imgLogo;

        @BindView(R.id.txt_left_item)
        TextView txtTitle;

        public ViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }
}

RightListAdapter.java

package com.bwie.complexdemo.adapter;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.bwie.complexdemo.R;
import com.bwie.complexdemo.entity.LeftCategory;
import com.bwie.complexdemo.entity.RightCategory;
import com.bwie.complexdemo.entity.SecondProduct;

import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;

/**
 * Created by eric on 2018/4/18.
 */

public class RightListAdapter extends RecyclerView.Adapter<RightListAdapter.ViewHolder> {
    private Context context;
    private List<RightCategory> list;

    public RightListAdapter(Context context, List<RightCategory> list) {
        this.context = context;
        this.list = list;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = View.inflate(context, R.layout.item_right_first, null);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.txtTitle.setText(list.get(position).getName());

        // 对应的二级的RecyclerView列表
        // 数据对应的是一条data里面的list
        SecondAdapter adapter = new SecondAdapter(context, list.get(position).getList());
        holder.rvSecond.setLayoutManager(new GridLayoutManager(context, 3));
        holder.rvSecond.setAdapter(adapter);
//        holder.rvSecond;
    }

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

    class ViewHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.txt_right_first)
        TextView txtTitle;

        @BindView(R.id.rv_second_right)
        RecyclerView rvSecond;

        public ViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }

    // 第二级的RecyclerView适配器
    class SecondAdapter extends RecyclerView.Adapter<SecondAdapter.SecondViewHolder> {
        private Context context;
        private List<SecondProduct> products;

        public SecondAdapter(Context context, List<SecondProduct> products) {
            this.context = context;
            this.products = products;
        }

        @NonNull
        @Override
        public SecondViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View view = View.inflate(context, R.layout.item_right_second, null);
            SecondViewHolder holder = new SecondViewHolder(view);
            return holder;
        }

        @Override
        public void onBindViewHolder(@NonNull SecondViewHolder holder, int position) {
            Glide.with(context).load(products.get(position).getIcon()).into(holder.imgLogo);
            holder.txtSecondTitle.setText(products.get(position).getName());
        }

        @Override
        public int getItemCount() {
            if (products != null) {
                return products.size();
            }
            return 0;
        }

        class SecondViewHolder extends RecyclerView.ViewHolder {
            @BindView(R.id.img_right_second_item)
            ImageView imgLogo;

            @BindView(R.id.txt_right_second_item)
            TextView txtSecondTitle;

            public SecondViewHolder(View itemView) {
                super(itemView);
                ButterKnife.bind(this, itemView);
            }
        }
    }
}

base

BaseApplication.java(记得在清单文件.name)

package com.bwie.complexdemo.base;

import android.app.Application;
import android.content.IntentFilter;

import com.bwie.complexdemo.entity.LeftCategory;
import com.bwie.complexdemo.entity.RightCategory;
import com.bwie.complexdemo.receiver.NetWorkStateReceiver;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BaseApplication extends Application {

    private NetWorkStateReceiver receiver;

    // 内存缓存
    private List<LeftCategory> leftCategories;
    private Map<String,List<RightCategory>> rightMap;

    private static BaseApplication instance;

    @Override
    public void onCreate() {
        super.onCreate();

        instance = this;
        rightMap = new HashMap<>();
        // 网络状态发生变化时候发出的广播
        IntentFilter filter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
        receiver = new NetWorkStateReceiver();
        registerReceiver(receiver, filter);
    }

    public static BaseApplication getInstance() {
        return instance;
    }

    @Override
    public void onTerminate() {
        super.onTerminate();
        if (receiver != null) {
            unregisterReceiver(receiver);
        }
    }

    public List<RightCategory> getRightCategories(String cid) {
        // 取出cid对应的内存缓存数据
        if (rightMap.containsKey(cid)) {
            return rightMap.get(cid);
        }else{
            return null;
        }
    }

    public void setRightCategories(String cid, List<RightCategory> rightCategories) {
        // 内存缓存中存cid对应的数据
        rightMap.put(cid, rightCategories);
    }

    public List<LeftCategory> getLeftCategories() {
        return leftCategories;
    }

    public void setLeftCategories(List<LeftCategory> leftCategories) {
        this.leftCategories = leftCategories;
    }
}

constant

NetState.java

package com.bwie.complexdemo.constant;

/**
 * Created by eric on 2018/4/19.
 */

public enum NetState {
    AVALIABLE,
    UNAVALIABLE
}

db

DaoMaster.java

package com.bwie.complexdemo.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.util.Log;

import org.greenrobot.greendao.AbstractDaoMaster;
import org.greenrobot.greendao.database.StandardDatabase;
import org.greenrobot.greendao.database.Database;
import org.greenrobot.greendao.database.DatabaseOpenHelper;
import org.greenrobot.greendao.identityscope.IdentityScopeType;


// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/**
 * Master of DAO (schema version 1): knows all DAOs.
 */
public class DaoMaster extends AbstractDaoMaster {
    public static final int SCHEMA_VERSION = 1;

    /** Creates underlying database table using DAOs. */
    public static void createAllTables(Database db, boolean ifNotExists) {
        LeftCategoryDao.createTable(db, ifNotExists);
        RightCategoryDao.createTable(db, ifNotExists);
        SecondProductDao.createTable(db, ifNotExists);
    }

    /** Drops underlying database table using DAOs. */
    public static void dropAllTables(Database db, boolean ifExists) {
        LeftCategoryDao.dropTable(db, ifExists);
        RightCategoryDao.dropTable(db, ifExists);
        SecondProductDao.dropTable(db, ifExists);
    }

    /**
     * WARNING: Drops all table on Upgrade! Use only during development.
     * Convenience method using a {@link DevOpenHelper}.
     */
    public static DaoSession newDevSession(Context context, String name) {
        Database db = new DevOpenHelper(context, name).getWritableDb();
        DaoMaster daoMaster = new DaoMaster(db);
        return daoMaster.newSession();
    }

    public DaoMaster(SQLiteDatabase db) {
        this(new StandardDatabase(db));
    }

    public DaoMaster(Database db) {
        super(db, SCHEMA_VERSION);
        registerDaoClass(LeftCategoryDao.class);
        registerDaoClass(RightCategoryDao.class);
        registerDaoClass(SecondProductDao.class);
    }

    public DaoSession newSession() {
        return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);
    }

    public DaoSession newSession(IdentityScopeType type) {
        return new DaoSession(db, type, daoConfigMap);
    }

    /**
     * Calls {@link #createAllTables(Database, boolean)} in {@link #onCreate(Database)} -
     */
    public static abstract class OpenHelper extends DatabaseOpenHelper {
        public OpenHelper(Context context, String name) {
            super(context, name, SCHEMA_VERSION);
        }

        public OpenHelper(Context context, String name, CursorFactory factory) {
            super(context, name, factory, SCHEMA_VERSION);
        }

        @Override
        public void onCreate(Database db) {
            Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION);
            createAllTables(db, false);
        }
    }

    /** WARNING: Drops all table on Upgrade! Use only during development. */
    public static class DevOpenHelper extends OpenHelper {
        public DevOpenHelper(Context context, String name) {
            super(context, name);
        }

        public DevOpenHelper(Context context, String name, CursorFactory factory) {
            super(context, name, factory);
        }

        @Override
        public void onUpgrade(Database db, int oldVersion, int newVersion) {
            Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
            dropAllTables(db, true);
            onCreate(db);
        }
    }

}

DaoSession.java

package com.bwie.complexdemo.db;

import java.util.Map;

import org.greenrobot.greendao.AbstractDao;
import org.greenrobot.greendao.AbstractDaoSession;
import org.greenrobot.greendao.database.Database;
import org.greenrobot.greendao.identityscope.IdentityScopeType;
import org.greenrobot.greendao.internal.DaoConfig;

import com.bwie.complexdemo.entity.LeftCategory;
import com.bwie.complexdemo.entity.RightCategory;
import com.bwie.complexdemo.entity.SecondProduct;

import com.bwie.complexdemo.db.LeftCategoryDao;
import com.bwie.complexdemo.db.RightCategoryDao;
import com.bwie.complexdemo.db.SecondProductDao;

// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.

/**
 * {@inheritDoc}
 * 
 * @see org.greenrobot.greendao.AbstractDaoSession
 */
public class DaoSession extends AbstractDaoSession {

    private final DaoConfig leftCategoryDaoConfig;
    private final DaoConfig rightCategoryDaoConfig;
    private final DaoConfig secondProductDaoConfig;

    private final LeftCategoryDao leftCategoryDao;
    private final RightCategoryDao rightCategoryDao;
    private final SecondProductDao secondProductDao;

    public DaoSession(Database db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig>
            daoConfigMap) {
        super(db);

        leftCategoryDaoConfig = daoConfigMap.get(LeftCategoryDao.class).clone();
        leftCategoryDaoConfig.initIdentityScope(type);

        rightCategoryDaoConfig = daoConfigMap.get(RightCategoryDao.class).clone();
        rightCategoryDaoConfig.initIdentityScope(type);

        secondProductDaoConfig = daoConfigMap.get(SecondProductDao.class).clone();
        secondProductDaoConfig.initIdentityScope(type);

        leftCategoryDao = new LeftCategoryDao(leftCategoryDaoConfig, this);
        rightCategoryDao = new RightCategoryDao(rightCategoryDaoConfig, this);
        secondProductDao = new SecondProductDao(secondProductDaoConfig, this);

        registerDao(LeftCategory.class, leftCategoryDao);
        registerDao(RightCategory.class, rightCategoryDao);
        registerDao(SecondProduct.class, secondProductDao);
    }

    public void clear() {
        leftCategoryDaoConfig.clearIdentityScope();
        rightCategoryDaoConfig.clearIdentityScope();
        secondProductDaoConfig.clearIdentityScope();
    }

    public LeftCategoryDao getLeftCategoryDao() {
        return leftCategoryDao;
    }

    public RightCategoryDao getRightCategoryDao() {
        return rightCategoryDao;
    }

    public SecondProductDao getSecondProductDao() {
        return secondProductDao;
    }

}

DBManager.java

package com.bwie.complexdemo.db;

import android.content.Context;

import com.bwie.complexdemo.entity.RightCategory;

/**
 * Created by eric on 2018/4/18.
 */

public class DBManager {
    private static volatile DBManager instance;
    private static final String DB_NAME = "complex.db";
    private final DaoSession daoSession;


    private DBManager(Context context) {
        DaoMaster.DevOpenHelper openHelper = new DaoMaster.DevOpenHelper(context, DB_NAME);
        DaoMaster daoMaster = new DaoMaster(openHelper.getWritableDatabase());
        daoSession = daoMaster.newSession();
    }

    public static DBManager getInstance(Context context) {
        if (instance == null) {
            synchronized (DBManager.class) {
                if (null == instance) {
                    instance = new DBManager(context);
                }
            }
        }
        return instance;
    }

    public LeftCategoryDao getLeftCategoryDao() {
        return daoSession.getLeftCategoryDao();
    }

    public RightCategoryDao getRightCategoryDao() {
        return daoSession.getRightCategoryDao();
    }

    public SecondProductDao getSecondProductDao() {
        return daoSession.getSecondProductDao();
    }
}

LeftCategoryDao.java

package com.bwie.complexdemo.db;

import android.database.Cursor;
import android.database.sqlite.SQLiteStatement;

import org.greenrobot.greendao.AbstractDao;
import org.greenrobot.greendao.Property;
import org.greenrobot.greendao.internal.DaoConfig;
import org.greenrobot.greendao.database.Database;
import org.greenrobot.greendao.database.DatabaseStatement;

import com.bwie.complexdemo.entity.LeftCategory;

// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/** 
 * DAO for table "LEFT_CATEGORY".
*/
public class LeftCategoryDao extends AbstractDao<LeftCategory, Long> {

    public static final String TABLENAME = "LEFT_CATEGORY";

    /**
     * Properties of entity LeftCategory.<br/>
     * Can be used for QueryBuilder and for referencing column names.
     */
    public static class Properties {
        public final static Property Cid = new Property(0, Long.class, "cid", true, "_id");
        public final static Property CreateTime = new Property(1, String.class, "createTime", false, "CREATE_TIME");
        public final static Property Icon = new Property(2, String.class, "icon", false, "ICON");
        public final static Property IsHome = new Property(3, int.class, "isHome", false, "IS_HOME");
        public final static Property Name = new Property(4, String.class, "name", false, "NAME");
    }


    public LeftCategoryDao(DaoConfig config) {
        super(config);
    }

    public LeftCategoryDao(DaoConfig config, DaoSession daoSession) {
        super(config, daoSession);
    }

    /** Creates the underlying database table. */
    public static void createTable(Database db, boolean ifNotExists) {
        String constraint = ifNotExists? "IF NOT EXISTS ": "";
        db.execSQL("CREATE TABLE " + constraint + "\"LEFT_CATEGORY\" (" + //
                "\"_id\" INTEGER PRIMARY KEY ," + // 0: cid
                "\"CREATE_TIME\" TEXT," + // 1: createTime
                "\"ICON\" TEXT," + // 2: icon
                "\"IS_HOME\" INTEGER NOT NULL ," + // 3: isHome
                "\"NAME\" TEXT);"); // 4: name
    }

    /** Drops the underlying database table. */
    public static void dropTable(Database db, boolean ifExists) {
        String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"LEFT_CATEGORY\"";
        db.execSQL(sql);
    }

    @Override
    protected final void bindValues(DatabaseStatement stmt, LeftCategory entity) {
        stmt.clearBindings();

        Long cid = entity.getCid();
        if (cid != null) {
            stmt.bindLong(1, cid);
        }

        String createTime = entity.getCreateTime();
        if (createTime != null) {
            stmt.bindString(2, createTime);
        }

        String icon = entity.getIcon();
        if (icon != null) {
            stmt.bindString(3, icon);
        }
        stmt.bindLong(4, entity.getIsHome());

        String name = entity.getName();
        if (name != null) {
            stmt.bindString(5, name);
        }
    }

    @Override
    protected final void bindValues(SQLiteStatement stmt, LeftCategory entity) {
        stmt.clearBindings();

        Long cid = entity.getCid();
        if (cid != null) {
            stmt.bindLong(1, cid);
        }

        String createTime = entity.getCreateTime();
        if (createTime != null) {
            stmt.bindString(2, createTime);
        }

        String icon = entity.getIcon();
        if (icon != null) {
            stmt.bindString(3, icon);
        }
        stmt.bindLong(4, entity.getIsHome());

        String name = entity.getName();
        if (name != null) {
            stmt.bindString(5, name);
        }
    }

    @Override
    public Long readKey(Cursor cursor, int offset) {
        return cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0);
    }    

    @Override
    public LeftCategory readEntity(Cursor cursor, int offset) {
        LeftCategory entity = new LeftCategory( //
            cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0), // cid
            cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1), // createTime
            cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // icon
            cursor.getInt(offset + 3), // isHome
            cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4) // name
        );
        return entity;
    }

    @Override
    public void readEntity(Cursor cursor, LeftCategory entity, int offset) {
        entity.setCid(cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0));
        entity.setCreateTime(cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1));
        entity.setIcon(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2));
        entity.setIsHome(cursor.getInt(offset + 3));
        entity.setName(cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4));
     }

    @Override
    protected final Long updateKeyAfterInsert(LeftCategory entity, long rowId) {
        entity.setCid(rowId);
        return rowId;
    }

    @Override
    public Long getKey(LeftCategory entity) {
        if(entity != null) {
            return entity.getCid();
        } else {
            return null;
        }
    }

    @Override
    public boolean hasKey(LeftCategory entity) {
        return entity.getCid() != null;
    }

    @Override
    protected final boolean isEntityUpdateable() {
        return true;
    }

}

RightCategoryDao.java

package com.bwie.complexdemo.db;

import android.database.Cursor;
import android.database.sqlite.SQLiteStatement;

import org.greenrobot.greendao.AbstractDao;
import org.greenrobot.greendao.Property;
import org.greenrobot.greendao.internal.DaoConfig;
import org.greenrobot.greendao.database.Database;
import org.greenrobot.greendao.database.DatabaseStatement;

import com.bwie.complexdemo.entity.RightCategory;

// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/** 
 * DAO for table "RIGHT_CATEGORY".
*/
public class RightCategoryDao extends AbstractDao<RightCategory, Long> {

    public static final String TABLENAME = "RIGHT_CATEGORY";

    /**
     * Properties of entity RightCategory.<br/>
     * Can be used for QueryBuilder and for referencing column names.
     */
    public static class Properties {
        public final static Property Cid = new Property(0, String.class, "cid", false, "CID");
        public final static Property Name = new Property(1, String.class, "name", false, "NAME");
        public final static Property Pcid = new Property(2, Long.class, "pcid", true, "_id");
    }


    public RightCategoryDao(DaoConfig config) {
        super(config);
    }

    public RightCategoryDao(DaoConfig config, DaoSession daoSession) {
        super(config, daoSession);
    }

    /** Creates the underlying database table. */
    public static void createTable(Database db, boolean ifNotExists) {
        String constraint = ifNotExists? "IF NOT EXISTS ": "";
        db.execSQL("CREATE TABLE " + constraint + "\"RIGHT_CATEGORY\" (" + //
                "\"CID\" TEXT," + // 0: cid
                "\"NAME\" TEXT," + // 1: name
                "\"_id\" INTEGER PRIMARY KEY );"); // 2: pcid
    }

    /** Drops the underlying database table. */
    public static void dropTable(Database db, boolean ifExists) {
        String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"RIGHT_CATEGORY\"";
        db.execSQL(sql);
    }

    @Override
    protected final void bindValues(DatabaseStatement stmt, RightCategory entity) {
        stmt.clearBindings();

        String cid = entity.getCid();
        if (cid != null) {
            stmt.bindString(1, cid);
        }

        String name = entity.getName();
        if (name != null) {
            stmt.bindString(2, name);
        }

        Long pcid = entity.getPcid();
        if (pcid != null) {
            stmt.bindLong(3, pcid);
        }
    }

    @Override
    protected final void bindValues(SQLiteStatement stmt, RightCategory entity) {
        stmt.clearBindings();

        String cid = entity.getCid();
        if (cid != null) {
            stmt.bindString(1, cid);
        }

        String name = entity.getName();
        if (name != null) {
            stmt.bindString(2, name);
        }

        Long pcid = entity.getPcid();
        if (pcid != null) {
            stmt.bindLong(3, pcid);
        }
    }

    @Override
    public Long readKey(Cursor cursor, int offset) {
        return cursor.isNull(offset + 2) ? null : cursor.getLong(offset + 2);
    }    

    @Override
    public RightCategory readEntity(Cursor cursor, int offset) {
        RightCategory entity = new RightCategory( //
            cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // cid
            cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1), // name
            cursor.isNull(offset + 2) ? null : cursor.getLong(offset + 2) // pcid
        );
        return entity;
    }

    @Override
    public void readEntity(Cursor cursor, RightCategory entity, int offset) {
        entity.setCid(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0));
        entity.setName(cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1));
        entity.setPcid(cursor.isNull(offset + 2) ? null : cursor.getLong(offset + 2));
     }

    @Override
    protected final Long updateKeyAfterInsert(RightCategory entity, long rowId) {
        entity.setPcid(rowId);
        return rowId;
    }

    @Override
    public Long getKey(RightCategory entity) {
        if(entity != null) {
            return entity.getPcid();
        } else {
            return null;
        }
    }

    @Override
    public boolean hasKey(RightCategory entity) {
        return entity.getPcid() != null;
    }

    @Override
    protected final boolean isEntityUpdateable() {
        return true;
    }

}

SecondProductDao.java

package com.bwie.complexdemo.db;

import android.database.Cursor;
import android.database.sqlite.SQLiteStatement;

import org.greenrobot.greendao.AbstractDao;
import org.greenrobot.greendao.Property;
import org.greenrobot.greendao.internal.DaoConfig;
import org.greenrobot.greendao.database.Database;
import org.greenrobot.greendao.database.DatabaseStatement;

import com.bwie.complexdemo.entity.SecondProduct;

// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/** 
 * DAO for table "SECOND_PRODUCT".
*/
public class SecondProductDao extends AbstractDao<SecondProduct, Long> {

    public static final String TABLENAME = "SECOND_PRODUCT";

    /**
     * Properties of entity SecondProduct.<br/>
     * Can be used for QueryBuilder and for referencing column names.
     */
    public static class Properties {
        public final static Property Icon = new Property(0, String.class, "icon", false, "ICON");
        public final static Property Name = new Property(1, String.class, "name", false, "NAME");
        public final static Property Pcid = new Property(2, int.class, "pcid", false, "PCID");
        public final static Property Pscid = new Property(3, Long.class, "pscid", true, "_id");
    }


    public SecondProductDao(DaoConfig config) {
        super(config);
    }

    public SecondProductDao(DaoConfig config, DaoSession daoSession) {
        super(config, daoSession);
    }

    /** Creates the underlying database table. */
    public static void createTable(Database db, boolean ifNotExists) {
        String constraint = ifNotExists? "IF NOT EXISTS ": "";
        db.execSQL("CREATE TABLE " + constraint + "\"SECOND_PRODUCT\" (" + //
                "\"ICON\" TEXT," + // 0: icon
                "\"NAME\" TEXT," + // 1: name
                "\"PCID\" INTEGER NOT NULL ," + // 2: pcid
                "\"_id\" INTEGER PRIMARY KEY );"); // 3: pscid
    }

    /** Drops the underlying database table. */
    public static void dropTable(Database db, boolean ifExists) {
        String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"SECOND_PRODUCT\"";
        db.execSQL(sql);
    }

    @Override
    protected final void bindValues(DatabaseStatement stmt, SecondProduct entity) {
        stmt.clearBindings();

        String icon = entity.getIcon();
        if (icon != null) {
            stmt.bindString(1, icon);
        }

        String name = entity.getName();
        if (name != null) {
            stmt.bindString(2, name);
        }
        stmt.bindLong(3, entity.getPcid());

        Long pscid = entity.getPscid();
        if (pscid != null) {
            stmt.bindLong(4, pscid);
        }
    }

    @Override
    protected final void bindValues(SQLiteStatement stmt, SecondProduct entity) {
        stmt.clearBindings();

        String icon = entity.getIcon();
        if (icon != null) {
            stmt.bindString(1, icon);
        }

        String name = entity.getName();
        if (name != null) {
            stmt.bindString(2, name);
        }
        stmt.bindLong(3, entity.getPcid());

        Long pscid = entity.getPscid();
        if (pscid != null) {
            stmt.bindLong(4, pscid);
        }
    }

    @Override
    public Long readKey(Cursor cursor, int offset) {
        return cursor.isNull(offset + 3) ? null : cursor.getLong(offset + 3);
    }    

    @Override
    public SecondProduct readEntity(Cursor cursor, int offset) {
        SecondProduct entity = new SecondProduct( //
            cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // icon
            cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1), // name
            cursor.getInt(offset + 2), // pcid
            cursor.isNull(offset + 3) ? null : cursor.getLong(offset + 3) // pscid
        );
        return entity;
    }

    @Override
    public void readEntity(Cursor cursor, SecondProduct entity, int offset) {
        entity.setIcon(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0));
        entity.setName(cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1));
        entity.setPcid(cursor.getInt(offset + 2));
        entity.setPscid(cursor.isNull(offset + 3) ? null : cursor.getLong(offset + 3));
     }

    @Override
    protected final Long updateKeyAfterInsert(SecondProduct entity, long rowId) {
        entity.setPscid(rowId);
        return rowId;
    }

    @Override
    public Long getKey(SecondProduct entity) {
        if(entity != null) {
            return entity.getPscid();
        } else {
            return null;
        }
    }

    @Override
    public boolean hasKey(SecondProduct entity) {
        return entity.getPscid() != null;
    }

    @Override
    protected final boolean isEntityUpdateable() {
        return true;
    }

}

entity

LeftCategory.java

package com.bwie.complexdemo.entity;

import com.google.gson.annotations.SerializedName;

import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Generated;

/**
 * Created by eric on 2018/4/18.
 */

@Entity
public class LeftCategory {
    @Id
    private Long cid;
    @SerializedName("createtime")
    private String createTime;
    private String icon;
    @SerializedName("ishome")
    private int isHome;
    private String name;

    @Generated(hash = 1247440683)
    public LeftCategory(Long cid, String createTime, String icon, int isHome,
            String name) {
        this.cid = cid;
        this.createTime = createTime;
        this.icon = icon;
        this.isHome = isHome;
        this.name = name;
    }

    @Generated(hash = 275471825)
    public LeftCategory() {
    }

    public Long getCid() {
        return cid;
    }

    public void setCid(Long cid) {
        this.cid = cid;
    }

    public String getCreateTime() {
        return createTime;
    }

    public void setCreateTime(String createTime) {
        this.createTime = createTime;
    }

    public String getIcon() {
        return icon;
    }

    public void setIcon(String icon) {
        this.icon = icon;
    }

    public int getIsHome() {
        return isHome;
    }

    public void setIsHome(int isHome) {
        this.isHome = isHome;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

MessageBean.java

package com.bwie.complexdemo.entity;

/**
 * Created by eric on 2018/4/18.
 */

public class MessageBean<T> {
    private String msg;
    private String code;
    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 T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

RightCategory.java

package com.bwie.complexdemo.entity;

import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.JoinEntity;
import org.greenrobot.greendao.annotation.Transient;

import java.util.List;
import org.greenrobot.greendao.annotation.Generated;

/**
 * Created by eric on 2018/4/18.
 */

@Entity
public class RightCategory {
    private String cid;
    private String name;
    @Transient
    private List<SecondProduct> list;
    @Id
    private Long pcid;
    @Generated(hash = 489537434)
    public RightCategory(String cid, String name, Long pcid) {
        this.cid = cid;
        this.name = name;
        this.pcid = pcid;
    }
    @Generated(hash = 1703583084)
    public RightCategory() {
    }
    public String getCid() {
        return this.cid;
    }
    public void setCid(String cid) {
        this.cid = cid;
    }
    public String getName() {
        return this.name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Long getPcid() {
        return this.pcid;
    }
    public void setPcid(Long pcid) {
        this.pcid = pcid;
    }

    public List<SecondProduct> getList() {
        return list;
    }

    public void setList(List<SecondProduct> list) {
        this.list = list;
    }
}

SecondProduct.java

package com.bwie.complexdemo.entity;

import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Generated;

/**
 * Created by eric on 2018/4/18.
 */

@Entity
public class SecondProduct {
    private String icon;
    private String name;
    private int pcid;
    @Id
    private Long pscid;

    @Generated(hash = 820941372)
    public SecondProduct(String icon, String name, int pcid, Long pscid) {
        this.icon = icon;
        this.name = name;
        this.pcid = pcid;
        this.pscid = pscid;
    }

    @Generated(hash = 1664098311)
    public SecondProduct() {
    }

    public String getIcon() {
        return icon;
    }

    public void setIcon(String icon) {
        this.icon = icon;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPcid() {
        return pcid;
    }

    public void setPcid(int pcid) {
        this.pcid = pcid;
    }

    public Long getPscid() {
        return pscid;
    }

    public void setPscid(Long pscid) {
        this.pscid = pscid;
    }
}

http

ApiService.java

package com.bwie.complexdemo.http;

import com.bwie.complexdemo.entity.LeftCategory;
import com.bwie.complexdemo.entity.MessageBean;
import com.bwie.complexdemo.entity.RightCategory;

import java.util.List;

import io.reactivex.Flowable;
import retrofit2.http.GET;
import retrofit2.http.Query;

/**
 * Created by eric on 2018/4/18.
 */

public interface ApiService {

    @GET("product/getCatagory")
    Flowable<MessageBean<List<LeftCategory>>> getFirstCategory();

    @GET("product/getProductCatagory")
    Flowable<MessageBean<List<RightCategory>>> getSecondCategory(@Query("cid") String cid);
}

ServerUrl.java

package com.bwie.complexdemo.http;

/**
 * Created by eric on 2018/4/18.
 */

public class ServerUrl {
    public static final String BASE_URL = "https://www.zhaoapi.cn/";
}

inter

IPresenter.java

package com.bwie.complexdemo.inter;

/**
 * Created by eric on 2018/4/18.
 */

public interface IPresenter<T> {
    void onReceived(T t);
    void onError(Throwable t);
}

IView.java

package com.bwie.complexdemo.inter;

/**
 * Created by eric on 2018/4/18.
 */

public interface IView<T> {
    void onSuccess(T t);

    void onFailed(Throwable t);
}

OnRecyclerViewItemClickListener.java

package com.bwie.complexdemo.inter;

/**
 * Created by eric on 2018/4/18.
 */

public interface OnRecyclerViewItemClickListener {
    void onItemClick(int position);
}

model

LeftModel.java

package com.bwie.complexdemo.model;

import android.content.Context;
import android.util.Log;

import com.bwie.complexdemo.base.BaseApplication;
import com.bwie.complexdemo.db.DBManager;
import com.bwie.complexdemo.db.LeftCategoryDao;
import com.bwie.complexdemo.entity.LeftCategory;
import com.bwie.complexdemo.entity.MessageBean;
import com.bwie.complexdemo.inter.IPresenter;
import com.bwie.complexdemo.utils.HttpUtils;
import com.bwie.complexdemo.utils.NetWorkUtils;

import java.util.ArrayList;
import java.util.List;

import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subscribers.DisposableSubscriber;

/**
 * Created by eric on 2018/4/18.
 */

public class LeftModel {
    private static final String TAG = "LeftModel";
    private IPresenter presenter;
    private Context context;

    public LeftModel(Context context, IPresenter presenter) {
        this.presenter = presenter;
        this.context = context;
    }

    /**
     * 网络请求
     */
    public void getData() {
        // 1. 先看下内存之中是否存在这个数据;
        List<LeftCategory> leftCategories = BaseApplication.getInstance().getLeftCategories();
        // 内存中不存在
        if (leftCategories == null) {
            getDataFromDBOrHttp(context);
        } else {
            presenter.onReceived(leftCategories);
        }
    }

    private void getDataFromDBOrHttp(Context context) {

        // 从数据库中查询
        LeftCategoryDao leftCategoryDao = DBManager.getInstance(context).getLeftCategoryDao();
        List<LeftCategory> leftCategories = leftCategoryDao.loadAll();
        // 数据库中有数据,则从数据库中获取
        if (leftCategories != null) {
            // 存到内存中一份
            BaseApplication.getInstance().setLeftCategories(leftCategories);
            presenter.onReceived(leftCategories);
        }
        // 数据库中没有数据,则从网络加载,数据库中有数据的时候,也从网络加载最新数据
        if (NetWorkUtils.getNetState(context)) {
            getDataFromHttp();
        }

    }

    private void getDataFromHttp() {
        // Retrofit+RxJava网络请求,解析数据
        HttpUtils.getInstance().getService()
                .getFirstCategory()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new DisposableSubscriber<MessageBean<List<LeftCategory>>>() {
                    @Override
                    public void onNext(MessageBean<List<LeftCategory>> listMessageBean) {
                        // 获取到数据之后,1.存到磁盘中一份
                        LeftCategoryDao dao = DBManager.getInstance(context).getLeftCategoryDao();
                        if (listMessageBean != null) {
                            List<LeftCategory> data = listMessageBean.getData();
                            if (data != null) {
                                // 有就替换,没有就插入
                                Log.i(TAG, "onNext: ");
                                // 把左侧列表数据,也就是data字段对应的列表数据插入数据库
                                dao.insertOrReplaceInTx(data);

                                // 2.还需要往内存中存一份
                                BaseApplication.getInstance().setLeftCategories(data);
                                // 将解析后的数据返回P层
                                presenter.onReceived(data);
                            }
                        }


                    }

                    @Override
                    public void onError(Throwable t) {
                        presenter.onError(t);
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }
}

RightModel.java

package com.bwie.complexdemo.model;

import android.content.Context;
import android.util.Log;

import com.bwie.complexdemo.base.BaseApplication;
import com.bwie.complexdemo.db.DBManager;
import com.bwie.complexdemo.db.RightCategoryDao;
import com.bwie.complexdemo.db.SecondProductDao;
import com.bwie.complexdemo.entity.MessageBean;
import com.bwie.complexdemo.entity.RightCategory;
import com.bwie.complexdemo.entity.SecondProduct;
import com.bwie.complexdemo.inter.IPresenter;
import com.bwie.complexdemo.utils.HttpUtils;
import com.bwie.complexdemo.utils.NetWorkUtils;

import org.greenrobot.greendao.query.Query;

import java.util.List;

import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subscribers.DisposableSubscriber;

/**
 * Created by eric on 2018/4/18.
 */

public class RightModel {
    private static final String TAG = "RightModel";
    private IPresenter presenter;
    private Context context;

    public RightModel(Context context, IPresenter presenter) {
        this.presenter = presenter;
        this.context = context;
    }

    public void getData(String cid) {
        // 1. 从内存缓存中取
        List<RightCategory> rightCategories = BaseApplication.getInstance().getRightCategories(cid);

        // 2. 内存缓存中没有数据则从数据库或者网络取
        if (rightCategories == null) {
            getDataFromDBOrHttp(context, cid);
        } else {
            Log.i(TAG, "从内存缓存中取");
            presenter.onReceived(rightCategories);
        }

    }

    private void getDataFromDBOrHttp(Context context, String cid) {
        // 先数据库取数据
        RightCategoryDao rightCategoryDao = DBManager.getInstance(context).getRightCategoryDao();
        // 根据cid查询出对应的条目
        List<RightCategory> rightCategories = rightCategoryDao.queryBuilder().where(RightCategoryDao.Properties.Cid.eq(cid))
                .build().list();

        SecondProductDao secondProductDao = DBManager.getInstance(context).getSecondProductDao();
        for (RightCategory rightCategory : rightCategories) {
            // 查询出子条目中pcid=外层pcid的条目
            List<SecondProduct> list = secondProductDao.queryBuilder().where(SecondProductDao.Properties.Pcid.eq(rightCategory.getPcid()))
                    .build().list();
            if (list != null) {
                rightCategory.setList(list);
            }
        }
        Log.i(TAG, "从数据库中取");
        // 保存到内存之中一份
        if (rightCategories != null) {
            if (rightCategories.size() > 0) {
                BaseApplication.getInstance().setRightCategories(cid, rightCategories);
            }
        }

//       List<RightCategory> rightCategories就是我们model层需要获取的数据
        // 数据返回给P层
        presenter.onReceived(rightCategories);

        if (NetWorkUtils.getNetState(context)) {
            getDataFromHttp(cid);
        }

    }

    private void getDataFromHttp(final String cid) {
        // RxJava+Retrofit做网络请求
        HttpUtils.getInstance().getService()
                .getSecondCategory(cid)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new DisposableSubscriber<MessageBean<List<RightCategory>>>() {
                    @Override
                    public void onNext(MessageBean<List<RightCategory>> listMessageBean) {
                        if (listMessageBean != null) {
                            // 对应的是data字段里面的列表
                            List<RightCategory> data = listMessageBean.getData();
                            if (data != null) {
                                // 右侧列表的第一级
                                RightCategoryDao dao = DBManager.getInstance(context).getRightCategoryDao();
                                dao.insertOrReplaceInTx(data);
                                // 内层集合
                                for (RightCategory inner : data) {
                                    // 循环遍历,将每一个data里面的list字段插入到数据库
                                    List<SecondProduct> innerList = inner.getList();
                                    if (innerList != null) {
                                        SecondProductDao productDao = DBManager.getInstance(context).getSecondProductDao();
                                        // 插入内层的数据库列表
                                        productDao.insertOrReplaceInTx(innerList);
                                    }
                                }

                                // 再添加进内存缓存
                                if (data.size() > 0) {
                                    BaseApplication.getInstance().setRightCategories(cid, data);
                                }
                                Log.i(TAG, "从网络取");
                                // 获取到数据之后传给P层
                                presenter.onReceived(data);
                            }
                        }


                    }

                    @Override
                    public void onError(Throwable t) {
                        presenter.onError(t);
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }
}

presenter

LeftPresenter.java

package com.bwie.complexdemo.presenter;

import android.content.Context;

import com.bwie.complexdemo.entity.LeftCategory;
import com.bwie.complexdemo.entity.MessageBean;
import com.bwie.complexdemo.inter.IPresenter;
import com.bwie.complexdemo.inter.IView;
import com.bwie.complexdemo.model.LeftModel;

import java.util.List;

/**
 * Created by eric on 2018/4/18.
 */

public class LeftPresenter implements IPresenter<List<LeftCategory>> {

    private IView iv;
    private Context context;

    public LeftPresenter() {

    }

    public LeftPresenter(Context context) {
        this.context = context;
    }

    public void attachView(IView iv) {
        this.iv = iv;
    }

    public void detachView() {
        if (iv != null) {
            iv = null;
        }
    }

    public void getData() {
        // 请求M层获取网络数据
        LeftModel model = new LeftModel(context, this);
        model.getData();
    }


    @Override
    public void onReceived(List<LeftCategory> listMessageBean) {
        // 接受到M层返回的数据之后
        // 把数据返回给V层
        iv.onSuccess(listMessageBean);
    }

    @Override
    public void onError(Throwable t) {
        iv.onFailed(t);
    }
}

RightPresenter.java

package com.bwie.complexdemo.presenter;

import android.content.Context;

import com.bwie.complexdemo.entity.MessageBean;
import com.bwie.complexdemo.entity.RightCategory;
import com.bwie.complexdemo.inter.IPresenter;
import com.bwie.complexdemo.inter.IView;
import com.bwie.complexdemo.model.RightModel;

import java.util.List;

/**
 * Created by eric on 2018/4/18.
 */

public class RightPresenter implements IPresenter<List<RightCategory>> {

    private IView iv;
    private Context context;

    public RightPresenter() {

    }

    public RightPresenter(Context context) {
        this.context = context;
    }

    public void attachView(IView iv) {
        this.iv = iv;
    }

    public void detachView() {
        if (iv != null) {
            iv = null;
        }
    }

    // 调用M层来获取网络数据
    public void getData(String cid) {
        RightModel model = new RightModel(context,this);
        model.getData(cid);
    }


    // 接受M层获取的数据
    @Override
    public void onReceived(List<RightCategory> listMessageBean) {
        // 把数据回调给V层
        iv.onSuccess(listMessageBean);
    }

    @Override
    public void onError(Throwable t) {
        iv.onFailed(t);
    }
}

receiver

NetWorkStateReceiver.java

package com.bwie.complexdemo.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;

import com.bwie.complexdemo.constant.NetState;
import com.bwie.complexdemo.utils.NetWorkUtils;

import org.greenrobot.eventbus.EventBus;

/**
 * Created by eric on 2018/4/19.
 */

public class NetWorkStateReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        System.out.println("网络状态发生变化");
        // 监听到网络状态发生变化的时候,将当前的网络状态发送出去
        EventBus.getDefault().post(NetWorkUtils.getNetState(context) ? NetState.AVALIABLE : NetState.UNAVALIABLE);
    }
}

utils

HttpUtils.java

package com.bwie.complexdemo.utils;

import com.bwie.complexdemo.http.ApiService;
import com.bwie.complexdemo.http.ServerUrl;

import okhttp3.OkHttpClient;
import okhttp3.internal.cache.CacheInterceptor;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by eric on 2018/4/18.
 */

public class HttpUtils {
    // 单例工具类
    private static volatile HttpUtils instance;

    private ApiService apiService;
    private Retrofit retrofit;

    private HttpUtils() {
        // 日志拦截器
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);

        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .build();

        retrofit = new Retrofit.Builder()
                .baseUrl(ServerUrl.BASE_URL)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
    }

    public static HttpUtils getInstance() {
        if (instance == null) {
            synchronized (HttpUtils.class) {
                if (null == instance) {
                    instance = new HttpUtils();
                }
            }
        }
        return instance;
    }

    public ApiService getService() {
        return retrofit.create(ApiService.class);
    }
}

NetWorkUtils.java

package com.bwie.complexdemo.utils;

import android.annotation.TargetApi;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.os.Build;

/**
 * Created by eric on 2018/4/19.
 */

public class NetWorkUtils {
    // 获取当前网络状态
    public static boolean getNetState(Context context) {
        if (Build.VERSION.SDK_INT < 21) {
            return checkNetStateBelow21(context);
        } else {
            return checkNetStateAbove21(context);
        }
    }


    // API版本21以下时调用此方法进行检测
    //因为API21后getNetworkInfo(int networkType)方法被弃用
    public static boolean checkNetStateBelow21(Context context) {
        //步骤1:通过Context.getSystemService(Context.CONNECTIVITY_SERVICE)获得ConnectivityManager对象
        ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

        //步骤2:获取ConnectivityManager对象对应的NetworkInfo对象
        //NetworkInfo对象包含网络连接的所有信息
        //步骤3:根据需要取出网络连接信息
        //获取WIFI连接的信息
        NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
        boolean isWifiConn = networkInfo.isConnected();

        //获取移动数据连接的信息
        networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
        boolean isMobileConn = networkInfo.isConnected();
        return isWifiConn || isMobileConn;
    }

    //API版本23及以上时调用此方法进行网络的检测
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public static boolean checkNetStateAbove21(Context context) {
        //获得ConnectivityManager对象
        ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

        //获取所有网络连接的信息
        Network[] networks = connMgr.getAllNetworks();
        //用于存放网络连接信息
        StringBuilder sb = new StringBuilder();
        //通过循环将网络信息逐个取出来
        for (int i = 0; i < networks.length; i++) {
            //获取ConnectivityManager对象对应的NetworkInfo对象
            NetworkInfo networkInfo = connMgr.getNetworkInfo(networks[i]);
            if (networkInfo.isConnected()) {
                return true;
            }
        }
        return false;
    }
}

view

LeftFragment.java

package com.bwie.complexdemo.view;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.bwie.complexdemo.R;
import com.bwie.complexdemo.adapter.LeftListAdapter;
import com.bwie.complexdemo.base.BaseApplication;
import com.bwie.complexdemo.entity.LeftCategory;
import com.bwie.complexdemo.entity.MessageBean;
import com.bwie.complexdemo.inter.IView;
import com.bwie.complexdemo.inter.OnRecyclerViewItemClickListener;
import com.bwie.complexdemo.presenter.LeftPresenter;

import org.greenrobot.eventbus.EventBus;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;

/**
 * Created by eric on 2018/4/18.
 */

public class LeftFragment extends Fragment implements IView<List<LeftCategory>> {
    private static final String TAG = "LeftFragment";
    /**
     * 左侧列表的视图
     */
    @BindView(R.id.rv_left)
    RecyclerView rvLeft;

    Unbinder unbinder;
    private Context mActivity;

    private LeftListAdapter adapter;
    private List<LeftCategory> list;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mActivity = getActivity();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_left, null);
        unbinder = ButterKnife.bind(this, view);
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        // RecyclerView设置适配器
        list = new ArrayList<>();
        adapter = new LeftListAdapter(mActivity, list);

        // 左侧的条目点击监听
        adapter.setListener(new OnRecyclerViewItemClickListener() {
            @Override
            public void onItemClick(int position) {
                Long cid = list.get(position).getCid();
                // 左侧列表的cid传出去,右侧列表进行接收
                EventBus.getDefault().post(cid);
            }
        });

        rvLeft.setLayoutManager(new LinearLayoutManager(mActivity));
        rvLeft.setAdapter(adapter);

        // 左侧的Presenter
        LeftPresenter presenter = new LeftPresenter(BaseApplication.getInstance().getApplicationContext());
        presenter.attachView(this);
        // 左侧的Present调用自己的请求数据的方法来获取左侧所有的数据
        presenter.getData();
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        unbinder.unbind();
    }

    @Override
    public void onSuccess(List<LeftCategory> data) {
        // 获取到网络数据之后,把数据的列表添加到原有的列表之中,然后刷新适配器
        if (data != null) {
            list.addAll(data);
            adapter.notifyDataSetChanged();
        }

    }

    @Override
    public void onFailed(Throwable t) {
        Toast.makeText(mActivity, "数据获取失败:" + t.getMessage(), Toast.LENGTH_SHORT).show();
    }
}

RightFragment.java

package com.bwie.complexdemo.view;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.bwie.complexdemo.R;
import com.bwie.complexdemo.adapter.LeftListAdapter;
import com.bwie.complexdemo.adapter.RightListAdapter;
import com.bwie.complexdemo.base.BaseApplication;
import com.bwie.complexdemo.constant.NetState;
import com.bwie.complexdemo.entity.LeftCategory;
import com.bwie.complexdemo.entity.MessageBean;
import com.bwie.complexdemo.entity.RightCategory;
import com.bwie.complexdemo.inter.IView;
import com.bwie.complexdemo.presenter.LeftPresenter;
import com.bwie.complexdemo.presenter.RightPresenter;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;

/**
 * Created by eric on 2018/4/18.
 */

public class RightFragment extends Fragment implements IView<List<RightCategory>> {
    /**
     * 左侧列表的视图
     */
    @BindView(R.id.rv_right)
    RecyclerView rvRight;

    Unbinder unbinder;
    private Context mActivity;

    private RightListAdapter adapter;
    private List<RightCategory> list;
    private RightPresenter presenter;

    private Long currentCid = 1L;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mActivity = getActivity();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_right, null);
        unbinder = ButterKnife.bind(this, view);
        // 注册EventBus
        EventBus.getDefault().register(this);
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        // 列表展示适配器
        list = new ArrayList<>();
        adapter = new RightListAdapter(mActivity, list);

        rvRight.setLayoutManager(new LinearLayoutManager(mActivity));
        rvRight.setAdapter(adapter);

        rvRight.addItemDecoration(new DividerItemDecoration(mActivity, DividerItemDecoration.VERTICAL));

        // 右侧的P层对象
        presenter = new RightPresenter(BaseApplication.getInstance().getApplicationContext());
        presenter.attachView(this);
        // 一开始的时候默认获取第一条数据
        presenter.getData(String.valueOf(currentCid));
    }


    // 接收左侧传过来的列表cid
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void receiveData(Long cid) {
        // 接收到左侧的cid之后做网络请求,获取数据,刷新适配器
        currentCid = cid;
        presenter.getData(String.valueOf(cid));
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void netState(NetState state) {
        if (state == NetState.AVALIABLE) {
            presenter.getData(String.valueOf(currentCid));
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        // 取消EventBus注册
        EventBus.getDefault().unregister(this);
        unbinder.unbind();
    }

    @Override
    public void onSuccess(List<RightCategory> data) {
        // 获取到数据之后,把数据添加到原有集合中,之后刷新适配器
        if (data != null) {
            list.clear();
            list.addAll(data);
            adapter.notifyDataSetChanged();
        }

    }

    @Override
    public void onFailed(Throwable t) {
        list.clear();
        adapter.notifyDataSetChanged();
        Toast.makeText(mActivity, "数据获取失败:" + t.getMessage(), Toast.LENGTH_SHORT).show();
    }
}

MainActivity.java

package com.bwie.complexdemo;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

//    /**
//     * 左侧Fragment
//     */
//    @BindView(R.id.fragment_left)
//    Fragment fragmentLeft;
//    /**
//     * 右侧Fragment
//     */
//    @BindView(R.id.fragment_right)
//    Fragment fragmentRight;

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

    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值