最近刚刚学完MVP+Rxjava2+Retrofit2,于是迫不及待的想写个demo,也希望可以帮助和我一样的新人学这些技术(刚入门的时候还是挺难的),demo使用了聚合数据获取新闻信息
来看一下demo的效果:
推荐几位大神的文章,希望对小伙伴学习这些有帮助:
Android Gilde教程 https://blog.csdn.net/qq_32368129/article/details/69526148
这可能是最好的RxJava 2.x 教程 http://www.apkbus.com/blog-898535-68185.html
Android之ButterKnife用法详解 https://blog.csdn.net/leavessilent/article/details/60872096
Android MVP开发模式 google 官方Mvp架构详解 https://blog.csdn.net/jungle_pig/article/details/65626469
这是一份很详细的 Retrofit 2.0 使用教程(含实例讲解) https://blog.csdn.net/carson_ho/article/details/73732076
("▔□▔),写了这么多好像还是没有进入正轨,是时候来操作一波了(ノ>▽<。)ノ
Gradle配置
//RecyclerView
compile 'com.android.support:design:26.+'
//Rxjava2
compile"io.reactivex.rxjava2:rxjava:2.1.1"
compile'io.reactivex.rxjava2:rxandroid:2.0.2'
//Retrofit2
compile'com.squareup.retrofit2:retrofit:2.3.0'
compile'com.squareup.retrofit2:converter-gson:2.3.0'
compile'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
// okHttp
compile 'com.squareup.okhttp3:okhttp:3.4.1'
compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
//Gilde
compile 'com.github.bumptech.glide:glide:3.7.0'
//CradView
compile 'com.android.support:cardview-v7:26.+'
//Butterkinfe
compile 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
项目结构:
项目结构参考上方提供的谷歌官方MVP项目结构
第一步创建BaseView和BasePresenter,我这里的BasePresenter接口实际上没用到什么东西,是空的所以就不贴出来了
package com.example.administrator.mvpdemo;
/**
* Created by Administrator on 2018/9/8.
*/
public interface BaseView {
void showLodading();
void dimissLoading();
}
第二步创建一个MainContract,用于管理BaseView和BasePresenter接口
package com.example.administrator.mvpdemo.Presenter.Contract;
import com.example.administrator.mvpdemo.BaseView;
import com.example.administrator.mvpdemo.Bean.ResultBean;
import com.example.administrator.mvpdemo.Presenter.BasePresenter;
import java.util.List;
/**
* Created by Administrator on 2018/9/8.
*/
public interface MainContract {
interface Presenter extends BasePresenter{
//实现请求数据
void requestData();
}
interface View extends BaseView{
void showResult(List<ResultBean.DataBean> datas); //显示数据
void showNodata(); //没有数据
void showError(String msg);//出现错误
}
}
第三步准备解析数据的实体类
package com.example.administrator.mvpdemo.Bean;
import java.util.List;
/**
* Created by Administrator on 2018/9/9.
*/
public class NewsBean<T> {
private String reason;
private T result;
private int error_code;
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public T getResult() {
return result;
}
public void setResult(T result) {
this.result = result;
}
public int getError_code() {
return error_code;
}
public void setError_code(int error_code) {
this.error_code = error_code;
}
}
还有一个ResultBean,由于篇幅问题就不贴出来了,GsonFormat一下就行,源码最后会提供下载的
第四步创建 用于描述网络请求 的接口
package com.example.administrator.mvpdemo.Data;
import com.example.administrator.mvpdemo.Bean.NewsBean;
import com.example.administrator.mvpdemo.Bean.ResultBean;
import io.reactivex.Observable;
import retrofit2.http.GET;
import retrofit2.http.Query;
/**
* Created by Administrator on 2018/9/9.
*/
// 创建 用于描述网络请求 的接口
public interface ApiService {
public static final String Base_url="http://v.juhe.cn/toutiao/";
@GET("index")
Observable <NewsBean<ResultBean>> getApp(@Query("typ") String type,@Query("key") String key);
}
第五步创建Retrofit实例
package com.example.administrator.mvpdemo.Data;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
/**
* Created by Administrator on 2018/9/9.
*/
public class httpManger {
public OkHttpClient getOkhttp(){
// log用拦截器
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
// 开发模式记录整个body,否则只记录基本信息如返回200,http协议版本等
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
// 如果使用到HTTPS,我们需要创建SSLSocketFactory,并设置到client
// SSLSocketFactory sslSocketFactory = null;
return new OkHttpClient.Builder()
// HeadInterceptor实现了Interceptor,用来往Request Header添加一些业务相关数据,如APP版本,token信息
// .addInterceptor(new HeadInterceptor())
.addInterceptor(logging)
// 连接超时时间设置
.connectTimeout(10, TimeUnit.SECONDS)
// 读取超时时间设置
.readTimeout(10, TimeUnit.SECONDS)
.build();
}
// 创建 Retrofit 实例
public Retrofit getRetrofit(OkHttpClient okHttpClient){
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(ApiService.Base_url) //添加url地址
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.build();
return retrofit;
}
}
第六步实现model层逻辑
package com.example.administrator.mvpdemo.Model;
import com.example.administrator.mvpdemo.Bean.NewsBean;
import com.example.administrator.mvpdemo.Bean.ResultBean;
import com.example.administrator.mvpdemo.Data.ApiService;
import com.example.administrator.mvpdemo.Data.httpManger;
import io.reactivex.Observable;
/**
* Created by Administrator on 2018/9/8.
*/
//model用于提供数据支持模型
public class UseInfoModel {
public Observable<NewsBean<ResultBean>> getNews(){
// 步骤五 创建 网络请求接口实例
httpManger manger=new httpManger();
ApiService apiService= manger.getRetrofit(manger.getOkhttp()).create(ApiService.class);
//步骤六 实现异步请求
return apiService.getApp("top","bc0a3a53be1e97115c2313e638662cae");//实际上这个是Observable<NewBean<ResultBean>>
}
}
第七步 MainPresenter用于和View层与model层交互
package com.example.administrator.mvpdemo.Presenter;
import com.example.administrator.mvpdemo.Bean.NewsBean;
import com.example.administrator.mvpdemo.Bean.ResultBean;
import com.example.administrator.mvpdemo.Data.ApiService;
import com.example.administrator.mvpdemo.Data.httpManger;
import com.example.administrator.mvpdemo.Model.UseInfoModel;
import com.example.administrator.mvpdemo.Presenter.Contract.MainContract;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.internal.observers.SubscriberCompletableObserver;
import io.reactivex.schedulers.Schedulers;
/**
* Created by Administrator on 2018/9/8.
*/
public class MainPresenter implements MainContract.Presenter {
MainContract.View mView;
UseInfoModel model=new UseInfoModel();
public MainPresenter(MainContract.View mView) {
this.mView = mView;
}
@Override
public void requestData() {
mView.showLodading();
model.getNews()
.subscribeOn(Schedulers.io()) //被观察者所在线程 io线程
.observeOn(AndroidSchedulers.mainThread()) //观察者所在线程 主线程
.subscribe(new Observer<NewsBean<ResultBean>>() {
Disposable mDisposable;
@Override
public void onSubscribe(@NonNull Disposable d) {
mDisposable=d;
}
@Override
public void onNext(@NonNull NewsBean<ResultBean> resultBeanNewsBean) {
if (resultBeanNewsBean!=null){
mView.showResult(resultBeanNewsBean.getResult().getData());
}else {
mView.showNodata();
}
mView.dimissLoading();
}
@Override
public void onError(@NonNull Throwable e) {
mView.dimissLoading();
}
@Override
public void onComplete() {
mView.dimissLoading();
}
});
}
}
最后贴上MainActivity代码
package com.example.administrator.mvpdemo;
import android.app.ProgressDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.Toast;
import com.example.administrator.mvpdemo.Adapter.MyRecyclerViewAdapter;
import com.example.administrator.mvpdemo.Bean.ResultBean;
import com.example.administrator.mvpdemo.Presenter.Contract.MainContract;
import com.example.administrator.mvpdemo.Presenter.MainPresenter;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
public class MainActivity extends AppCompatActivity implements MainContract.View{
@BindView(R.id.recyclerView)
RecyclerView mRecyclerView;
ProgressDialog dialog;
MyRecyclerViewAdapter adapter;
MainContract.Presenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
dialog=new ProgressDialog(this);
presenter=new MainPresenter(this);
initData();
}
private void initData() {
presenter.requestData();
}
@Override
public void showLodading() {
dialog.show();
}
@Override
public void dimissLoading() {
if (dialog.isShowing()){
dialog.dismiss();
}
}
@Override
public void showResult(List<ResultBean.DataBean> datas) {
initRecycler(datas);
}
private void initRecycler(List<ResultBean.DataBean> datas) {
mRecyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));
adapter=new MyRecyclerViewAdapter(this,datas);
mRecyclerView.setAdapter(adapter);
}
@Override
public void showNodata() {
Toast.makeText(this,"服务器炸了",Toast.LENGTH_SHORT).show();
}
@Override
public void showError(String msg) {
//这个里面用于判断错误
}
}
实际上也可以导入Dagger2依赖,不过个人感觉有些难,而且这种小demo用上Dagger2有些画蛇添足的意味吧,但也可以试试,而且这个demo完全可以在加工一下成为一个新闻app毕业设计。
写的感觉不够简洁,希望能够有所帮助吧,哈哈哈(●'◡'●)ノ
附上源码百度云盘链接
链接:https://pan.baidu.com/s/1cNBpsl4MQjgmqyuGi7OZ_Q 密码:pny7