使用的依赖和权限
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
implementation 'com.roughike:bottom-bar:1.3.3' implementation 'com.jcodecraeer:xrecyclerview:1.3.2' implementation 'com.android.support:design:27.1.1' implementation 'com.squareup.retrofit2:retrofit:2.4.0' implementation "io.reactivex.rxjava2:rxjava:2.1.13"//使retrofit支持Rxjava implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0' implementation 'com.squareup.retrofit2:converter-gson:2.4.0' //使retrofit支持Gson解析 implementation 'io.reactivex.rxjava2:rxandroid:2.0.2' implementation 'com.google.dagger:dagger:2.8' annotationProcessor 'com.google.dagger:dagger-compiler:2.7' implementation 'com.jakewharton:butterknife:8.8.1' annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' implementation 'com.facebook.fresco:fresco:1.9.0' implementation 'org.greenrobot:greendao:3.2.2' // add library
apply plugin: 'org.greenrobot.greendao' // apply plugin android {}
在build.gardle文件中的依赖
repositories { google() jcenter() mavenCentral() // add repository } dependencies { classpath 'com.android.tools.build:gradle:3.1.2' classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
activity_my_duan_zi
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MyDuanZiActivity"> <FrameLayout android:id="@+id/fl" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
fragment_duanzi
<?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"> <RelativeLayout android:layout_width="match_parent" android:layout_height="50dp" android:background="#FF1ABFD9"> <ImageView android:layout_width="40dp" android:layout_height="40dp" android:layout_centerVertical="true" android:background="@drawable/user_icon"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:layout_centerVertical="true" android:textSize="18dp" android:text="段子"/> <ImageView android:layout_width="40dp" android:layout_height="40dp" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:background="@drawable/edit_icon"/> </RelativeLayout> <com.jcodecraeer.xrecyclerview.XRecyclerView android:id="@+id/xrl" android:layout_width="match_parent" android:layout_height="match_parent"> </com.jcodecraeer.xrecyclerview.XRecyclerView> </LinearLayout>
xrv_layout
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:fresco="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/img" android:layout_width="70dp" android:layout_height="70dp" android:layout_margin="3dp" fresco:roundAsCircle="true" /> <LinearLayout android:layout_width="100dp" android:layout_height="match_parent" android:layout_margin="3dp" android:orientation="vertical"> <TextView android:id="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="123" android:textColor="#f00" android:textSize="16sp" /> <TextView android:id="@+id/tv_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="123" android:textSize="16sp" /> </LinearLayout> <ImageView android:layout_width="30dp" android:layout_height="30dp" android:layout_gravity="center_vertical" android:layout_marginLeft="150dp" android:src="@drawable/add_icon" /> </LinearLayout> <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/img_xia" android:layout_width="match_parent" android:layout_height="200dp" /> </LinearLayout
MyDuanZiActivity
import android.support.v4.app.FragmentManager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import com.bwie.test.myduanzi.duanzi.DuanziFragment; public class MyDuanZiActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my_duan_zi); //隐藏原有标题 getSupportActionBar().hide(); DuanziFragment duanziFragment = new DuanziFragment(); FragmentManager manager = getSupportFragmentManager(); manager.beginTransaction().replace(R.id.fl, duanziFragment).commit(); } }
DuanziFragment
import android.support.v4.app.Fragment; import android.support.v7.widget.LinearLayoutManager; import android.view.View; import com.bwie.test.adapter.DuanziAdapter; import com.bwie.test.app.MyApp; import com.bwie.test.bean.MyDataBean; import com.bwie.test.bean.MyDataBeanDao; import com.bwie.test.component.DaggerHttpComponent; import com.bwie.test.myduanzi.R; import com.bwie.test.bean.DuanziBean; import com.bwie.test.myduanzi.base.BaseFragment; import com.bwie.test.myduanzi.duanzi.contract.DuanziContract; import com.bwie.test.myduanzi.duanzi.presenter.DuanziPresenter; import com.jcodecraeer.xrecyclerview.XRecyclerView; import java.util.ArrayList; import java.util.List; public class DuanziFragment extends BaseFragment<DuanziPresenter> implements DuanziContract.View{ private XRecyclerView xlv; private List<DuanziBean.DataBean> list = new ArrayList<>(); private DuanziAdapter adapter; private boolean isRefresh = true; private int page = 1; @Override public int getContentLayout() { return R.layout.fragment_duanzi; } @Override public void initView(View view) { xlv = view.findViewById(R.id.xrl); xlv.setLayoutManager(new LinearLayoutManager(getContext())); adapter = new DuanziAdapter(getContext(), list); xlv.setAdapter(adapter); //判断数据库中是否有数据 MyDataBeanDao myDataBeanDao = MyApp.getDaoSession().getMyDataBeanDao(); List<MyDataBean> list = myDataBeanDao.queryBuilder().build().list(); if (list != null && list.size() > 0) { //说明数据库有数据 } else { mPresenter.getDuanzi(page + ""); } //设置刷新和加载更多监听 xlv.setLoadingListener(new XRecyclerView.LoadingListener() { @Override public void onRefresh() { //刷新 page = 1; isRefresh = true; mPresenter.getDuanzi(page + ""); } @Override public void onLoadMore() { //加载更多 page++; isRefresh = false; mPresenter.getDuanzi(page + ""); } }); } @Override public void inject() { DaggerHttpComponent.builder() .build() .inject(this); } @Override public void onSuccess(List<DuanziBean.DataBean> list) { if (isRefresh) { adapter.refresh(list); xlv.refreshComplete(); } else { adapter.loadMore(list); int listNum = adapter.getListNum(); xlv.loadMoreComplete(); int size = list.size(); int count = listNum + size; if (count >= 20) { xlv.setLoadingMoreEnabled(false); } } } }
app文件夹下MyApp
import android.app.Application; import com.bwie.test.bean.DaoMaster; import com.bwie.test.bean.DaoSession; import com.facebook.drawee.backends.pipeline.Fresco; public class MyApp extends Application{ private static DaoSession daoSession; @Override public void onCreate() { super.onCreate(); //初始化fresco Fresco.initialize(this); DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(this, "baway.db"); DaoMaster daoMaster = new DaoMaster(devOpenHelper.getWritableDb()); daoSession = daoMaster.newSession(); } public static DaoSession getDaoSession() { return daoSession; } }
adapter文件夹下DuanziAdapter
import android.content.Context; import android.support.annotation.NonNull; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.bwie.test.bean.DuanziBean; import com.bwie.test.myduanzi.R; import com.facebook.drawee.view.SimpleDraweeView; import java.util.List; public class DuanziAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private Context context; private List<DuanziBean.DataBean> list; private LayoutInflater inflater; public DuanziAdapter(Context context, List<DuanziBean.DataBean> list) { this.context = context; this.list = list; inflater = LayoutInflater.from(context); } @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = inflater.inflate(R.layout.xrv_layout, parent, false); return new MyViewHolder(view); } @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { DuanziBean.DataBean dataBean = list.get(position); MyViewHolder myViewHolder = (MyViewHolder) holder; String imgUrls = (String) dataBean.getImgUrls(); String imgUrl = ""; if (!TextUtils.isEmpty(imgUrls)) { imgUrl = imgUrls.split("\\|")[0]; } myViewHolder.iv.setImageURI(imgUrl); myViewHolder.tvName.setText(dataBean.getUser().getNickname() + ""); myViewHolder.tvTime.setText(dataBean.getCreateTime()); } @Override public int getItemCount() { return list.size(); } private class MyViewHolder extends RecyclerView.ViewHolder { private final SimpleDraweeView iv; private final TextView tvName; private final TextView tvTime; public MyViewHolder(View itemView) { super(itemView); iv = itemView.findViewById(R.id.img); tvName = itemView.findViewById(R.id.tv_name); tvTime = itemView.findViewById(R.id.tv_time); } } public void refresh(List<DuanziBean.DataBean> tempList) { //清楚原先集合里的内容 this.list.clear(); this.list.addAll(tempList); notifyDataSetChanged(); } public void loadMore(List<DuanziBean.DataBean> tempList) { this.list.addAll(tempList); notifyDataSetChanged(); } public int getListNum(){ return this.list.size(); } }
inter文件夹下IBase
import android.view.View; public interface IBase { int getContentLayout(); void initView(View view); void inject(); }
component文件夹下HttpComponent
import com.bwie.test.module.HttpModule; import com.bwie.test.myduanzi.duanzi.DuanziFragment; import dagger.Component; @Component(modules = HttpModule.class) public interface HttpComponent { void inject(DuanziFragment duanziFragment); }
module文件夹下HttpModule
import com.bwie.test.utils.Api; import com.bwie.test.utils.DuanziApi; import com.bwie.test.utils.DuanziApiService; import com.bwie.test.utils.MyInterceptor; import java.util.concurrent.TimeUnit; import dagger.Module; import dagger.Provides; import okhttp3.OkHttpClient; import retrofit2.Retrofit; import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; @Module public class HttpModule { @Provides OkHttpClient.Builder provideOkHttpClientBuilder() { return new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(20, TimeUnit.SECONDS) .writeTimeout(20, TimeUnit.SECONDS); } @Provides DuanziApi provideDuanApi(OkHttpClient.Builder builder) { builder.addInterceptor(new MyInterceptor()); Retrofit retrofit = new Retrofit.Builder() .baseUrl(Api.baseUrl) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .client(builder.build()) .build(); DuanziApiService duanziApiService = retrofit.create(DuanziApiService.class); return DuanziApi.getDuanziApi(duanziApiService); } }
base文件夹下BaseContract
public interface BaseContract { interface BasePresenter<T extends BaseView> { void attchView(T view); void detachView(); } interface BaseView { void showLoading(); void dismissLoading(); } }
BaseFragment
import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.bwie.test.inter.IBase; import javax.inject.Inject; public abstract class BaseFragment<T extends BaseContract.BasePresenter> extends Fragment implements IBase, BaseContract.BaseView { @Inject protected T mPresenter; @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { inject(); View view = inflater.inflate(getContentLayout(), null); mPresenter.attchView(this); initView(view); return view; } @Override public void onDestroy() { super.onDestroy(); mPresenter.detachView(); } @Override public void showLoading() { } @Override public void dismissLoading() { } }
BasePresenter
public class BasePresenter<T extends BaseContract.BaseView> implements BaseContract.BasePresenter<T> { protected T mView; @Override public void attchView(T view) { if(view !=null){ this.mView = view; } } @Override public void detachView() { if(mView !=null){ this.mView = null; } } }
contract文件夹下DuanziContract
import com.bwie.test.bean.DuanziBean; import com.bwie.test.myduanzi.base.BaseContract; import java.util.List; public interface DuanziContract { interface View extends BaseContract.BaseView{ void onSuccess(List<DuanziBean.DataBean> list); } interface Presenter extends BaseContract.BasePresenter<View> { void getDuanzi(String page); } }
presenter文件夹下DuanziPresenter
import android.annotation.SuppressLint; import com.bwie.test.app.MyApp; import com.bwie.test.bean.DaoSession; import com.bwie.test.bean.DuanziBean; import com.bwie.test.bean.MyDataBean; import com.bwie.test.bean.MyDataBeanDao; import com.bwie.test.myduanzi.base.BasePresenter; import com.bwie.test.myduanzi.duanzi.contract.DuanziContract; import com.bwie.test.utils.DuanziApi; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.functions.Consumer; import io.reactivex.functions.Function; import io.reactivex.schedulers.Schedulers; public class DuanziPresenter extends BasePresenter<DuanziContract.View> implements DuanziContract.Presenter { private DuanziApi duanziApi; @Inject public DuanziPresenter(DuanziApi duanziApi) { this.duanziApi = duanziApi; } @SuppressLint("CheckResult") @Override public void getDuanzi(String page) { duanziApi.getDuanzi(page) .subscribeOn(Schedulers.io()) .map(new Function<DuanziBean, List<DuanziBean.DataBean>>() { @Override public List<DuanziBean.DataBean> apply(DuanziBean duanziBean) throws Exception { return duanziBean.getData(); } }).observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<List<DuanziBean.DataBean>>() { @Override public void accept(List<DuanziBean.DataBean> dataBeans) throws Exception { DaoSession daoSession = MyApp.getDaoSession(); List<MyDataBean> list = new ArrayList<>(); MyDataBeanDao myDataBeanDao = daoSession.getMyDataBeanDao(); for (int i = 0; i < dataBeans.size(); i++) { DuanziBean.DataBean dataBean = dataBeans.get(i); MyDataBean myDataBean = new MyDataBean(); myDataBean.setAge(dataBean.getUser().getAge() + ""); myDataBean.setCommentNum(dataBean.getCommentNum() + ""); myDataBean.setContent(dataBean.getContent()); myDataBean.setCreateTime(dataBean.getCreateTime()); myDataBean.setFans(dataBean.getUser().getFans()); myDataBean.setFollow(dataBean.getUser().isFollow()); myDataBean.setIcon(dataBean.getUser().getIcon() + ""); myDataBean.setImgUrls((String)(dataBean.getImgUrls())); list.add(myDataBean); } myDataBeanDao.insertInTx(list); mView.onSuccess(dataBeans); } }); } }
utils文件夹下Api
public interface Api { String baseUrl = "https://www.zhaoapi.cn/"; }
DuanziApi
import com.bwie.test.bean.DuanziBean; import io.reactivex.Observable; public class DuanziApi { private static DuanziApi duanziApi; private DuanziApiService duanziApiService; public DuanziApi(DuanziApiService duanziApiService) { this.duanziApiService = duanziApiService; } public static DuanziApi getDuanziApi(DuanziApiService duanziApiService){ if (duanziApi == null){ duanziApi = new DuanziApi(duanziApiService); } return duanziApi; } public Observable<DuanziBean> getDuanzi(String page){ return duanziApiService.getDuanzi(page); } }
DuanziApiService
import com.bwie.test.bean.DuanziBean; import io.reactivex.Observable; import retrofit2.http.Field; import retrofit2.http.FormUrlEncoded; import retrofit2.http.POST; public interface DuanziApiService { @FormUrlEncoded @POST("quarter/getJokes") Observable<DuanziBean> getDuanzi(@Field("page") String page); }
MyInterceptor
import java.io.IOException; import okhttp3.FormBody; import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; public class MyInterceptor implements Interceptor{ @Override public Response intercept(Chain chain) throws IOException { FormBody.Builder builder = new FormBody.Builder(); Request originalRequest = chain.request(); FormBody formBody = (FormBody) originalRequest.body(); //获取原始请求 for (int i = 0; i<formBody.size(); i++){ builder.add(formBody.name(i), formBody.value(i)); } builder.add("source","android"); builder.add("appVersion","100"); FormBody body = builder.build(); //创建一个新的Request Request request = new Request.Builder() .url(originalRequest.url()) .post(body) .build(); Response response = chain.proceed(request); return response; } }
bean文件夹下DuanziBean
import java.util.List; public class DuanziBean { private String msg; private String code; private List<DataBean> 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 List<DataBean> getData() { return data; } public void setData(List<DataBean> data) { this.data = data; } public static class DataBean { private Object commentNum; private String content; private String createTime; private Object imgUrls; private int jid; private Object praiseNum; private Object shareNum; private int uid; private UserBean user; public Object getCommentNum() { return commentNum; } public void setCommentNum(Object commentNum) { this.commentNum = commentNum; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getCreateTime() { return createTime; } public void setCreateTime(String createTime) { this.createTime = createTime; } public Object getImgUrls() { return imgUrls; } public void setImgUrls(Object imgUrls) { this.imgUrls = imgUrls; } public int getJid() { return jid; } public void setJid(int jid) { this.jid = jid; } public Object getPraiseNum() { return praiseNum; } public void setPraiseNum(Object praiseNum) { this.praiseNum = praiseNum; } public Object getShareNum() { return shareNum; } public void setShareNum(Object shareNum) { this.shareNum = shareNum; } public int getUid() { return uid; } public void setUid(int uid) { this.uid = uid; } public UserBean getUser() { return user; } public void setUser(UserBean user) { this.user = user; } public static class UserBean { private Object age; private String fans; private boolean follow; private Object icon; private Object nickname; private String praiseNum; public Object getAge() { return age; } public void setAge(Object age) { this.age = age; } public String getFans() { return fans; } public void setFans(String fans) { this.fans = fans; } public boolean isFollow() { return follow; } public void setFollow(boolean follow) { this.follow = follow; } public Object getIcon() { return icon; } public void setIcon(Object icon) { this.icon = icon; } public Object getNickname() { return nickname; } public void setNickname(Object nickname) { this.nickname = nickname; } public String getPraiseNum() { return praiseNum; } public void setPraiseNum(String praiseNum) { this.praiseNum = praiseNum; } } } }
MyDataBean
import org.greenrobot.greendao.annotation.Entity; import org.greenrobot.greendao.annotation.Id; import org.greenrobot.greendao.annotation.Property; import org.greenrobot.greendao.annotation.Generated; @Entity public class MyDataBean { @Id private Long id; @Property private String commentNum; @Property private String content; @Property private String createTime; @Property private String imgUrls; @Property private int jid; @Property private String praiseNum; @Property private String shareNum; @Property private int uid; @Property private String age; @Property private String fans; @Property private boolean follow; @Property private String icon; @Property private String nickname; @Generated(hash = 1891157934) public MyDataBean(Long id, String commentNum, String content, String createTime, String imgUrls, int jid, String praiseNum, String shareNum, int uid, String age, String fans, boolean follow, String icon, String nickname) { this.id = id; this.commentNum = commentNum; this.content = content; this.createTime = createTime; this.imgUrls = imgUrls; this.jid = jid; this.praiseNum = praiseNum; this.shareNum = shareNum; this.uid = uid; this.age = age; this.fans = fans; this.follow = follow; this.icon = icon; this.nickname = nickname; } @Generated(hash = 650128772) public MyDataBean() { } public Long getId() { return this.id; } public void setId(Long id) { this.id = id; } public String getCommentNum() { return this.commentNum; } public void setCommentNum(String commentNum) { this.commentNum = commentNum; } public String getContent() { return this.content; } public void setContent(String content) { this.content = content; } public String getCreateTime() { return this.createTime; } public void setCreateTime(String createTime) { this.createTime = createTime; } public String getImgUrls() { return this.imgUrls; } public void setImgUrls(String imgUrls) { this.imgUrls = imgUrls; } public int getJid() { return this.jid; } public void setJid(int jid) { this.jid = jid; } public String getPraiseNum() { return this.praiseNum; } public void setPraiseNum(String praiseNum) { this.praiseNum = praiseNum; } public String getShareNum() { return this.shareNum; } public void setShareNum(String shareNum) { this.shareNum = shareNum; } public int getUid() { return this.uid; } public void setUid(int uid) { this.uid = uid; } public String getAge() { return this.age; } public void setAge(String age) { this.age = age; } public String getFans() { return this.fans; } public void setFans(String fans) { this.fans = fans; } public boolean getFollow() { return this.follow; } public void setFollow(boolean follow) { this.follow = follow; } public String getIcon() { return this.icon; } public void setIcon(String icon) { this.icon = icon; } public String getNickname() { return this.nickname; } public void setNickname(String nickname) { this.nickname = nickname; } }