带实际例子的Android架构MVP简述二「Java,MVP,Retrofit,RxJava,带Model」

由于鸿洋大佬开源接口停用(其他人滥用导致),该教程接口不再可用,有空再重写,抱歉

带实际例子的Android架构MVP简述二「Java,MVP,Retrofit,RxJava」

上一小节我们使用了一个简单的例子介绍了Mvp的介绍,在例子中我们是省略了Model层,只保留P层和View层(Activity),大概了解了Mvp数据的传递方式

但其实我们还可以再进行一层封装,也就是再封装一个Model层。这一小节我们就还使用上一篇的例子,新建一个项目,实现一样的功能,但是我们在原来的架构上再加入一个Mode层

  • 带实际例子的Android架构MVP简述一
  • 带实际例子的Android架构MVP简述二

项目源代码已经上传到仓库的Mvp_java_b文件夹内。本小节已经默认你看过上一小节了,所以有些重复的地方会简单略过

项目架构的搭建

创建项目,进行分包,和上一节的区别在于我们加入了model,这是用来存放Model层代码的。新的架构没有了View包,原本View包下的View接口将会写在presenter包下新加的contract包

为什么要这样做呢,因为Contract包下不仅仅会声明View接口,等等我们还会在contract包下对P层原来的Presenter类里的方法进行一些“约束”

带实际例子的Android架构MVP简述二「Java,MVP,Retrofit,RxJava,带Model」_第1张图片
分包.png

其他的,bean包用来存放网络请求实体类,net包用来放我们网络请求需要用到的类,还是一样,xml布局也一样




    

之后我们先从contract包开始,在presenter-contract包下创建InfoContract接口,在接口里面写我们原本放在view包下的view接口

/**
 * Created by 舍长 on 2019/1/3
 * describe:Contract层
 */
public interface InfoContract {

    /**
     * 学生信息view接口,用来进行P层和Activity的消息传输
     */
    interface infoView {
        void show(String msg);//请求返回的数据
    }
}

为什么不和上一节一样直接写出来,而是要写在里面呢,因为我们还要在这里,对P层的方法进行一些“约束”,我们加入P层实现接口

/**
 * Created by 舍长 on 2019/1/3
 * describe:Contract层
 */
public interface InfoContract {

    /**
     * 学生信息view接口,用来进行P层和Activity的消息传输
     */
    interface infoView {
        void show(String msg);//请求返回的数据
    }

    /**
     * 学生信息P层实现接口,用来对Presenter类进行一些"约束"
     */
    interface InfoIPresenter{
        void getData();//获取学生数据
        //方法1
        //方法2
        //方法3
    }
}

如何理解呢,你可以把InfoIPresenter接口当做是一个P层类的“目录”,加上我的伪代码,我们可以知道我们即将要写的P层类有多少个方法,要什么参数

这样写好之后我们心里就对Presenter类需要实现的方法有了一定的了解,如果你注释的完整的话别人一看就知道这个Presenter类具体实现了什么功能

其实这种设计模式也有专业名词,代理模式中的静态代理,不过我就爱叫它“目录”,简明易懂

它的使用上和View接口一样,我们创建InfoPresenter类,让该类继承于该接口,实现它的方法即可。接着我们声明View接口变量,在构造方法里面初始化,这是为了让Activity和View接口进行数据传递

/**
 * Created by 舍长 on 2019/1/4
 * describe:获取学生数据P层实现接口
 */
public class InfoPresenter implements InfoContract.InfoIPresenter {
    //声明View接口
    private InfoContract.infoView view;

    public InfoPresenter(InfoContract.infoView view) {
        this.view = view;
    }

    //获取学生数据
    @Override
    public void getData() {
        view.show("你好,世界");
    }
    
    
    //销毁View对象
    public void detachView() {
        view = null;
    }
}

到这里,我们如果在getData()方法里面写网络请求,就和上一节一样了,只是加入了contarct层这一调整。不过我们是要Model层的,所以我们得接着写Model层的代码。

Model层

我们需要先添加网络请求的依赖,并且将bean包下的bean类,net包下的Api接口,RetrofitHelper请求辅助类写好。参照上一节的网络请求部分,一模一样即可。

接着在model包下创建我们的InfoModel类,写一个获取数据的getData()方法。

import com.example.tonjies.mvp_java_b.net.Api;
import com.example.tonjies.mvp_java_b.net.RetrofitHelper;

import io.reactivex.Observable;

/**
 * Created by 舍长 on 2019/1/4
 * describe:请求学生信息的Model层类
 */
public class InfoModel {
    private Api api;

    public InfoModel() {
        api = RetrofitHelper.getInstance().getServer();
    }

    /**
     * 请求学生数据,返回Observable对象
     */
    public Observable getData(){
        //查询数据库,拿出参数
        //接受广播数据
        return api.getData();
    }
}

what,就这样!网络请求的回调方法被你吃了吗?其实是这样的,因为我们需要在请求的回调onNext()方法里面将数据传回Activity。如果我们在Model里写回调,传回去就麻烦了(也不是不可以,还是声明一个P层接口变量,然后写回调方法)

所以我们选择只把方法的返回值Observable对象返回,具体的回调还是在P层进行,这样看起来网络请求的方法是在P层实现,实际上还是在Model层,而且我们往往需要传递的参数不是那么简单,还是需要往数据库取出东西等等,参考伪代码注释

或者我们看一下这段代码

  //Model完成的
       Observable data = api.getData();

  //presenter完成的
        data.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer() {
                    @Override
                    public void onSubscribe(Disposable d) {
                    }

                    @Override
                    public void onNext(Student student) {
                    }

                    @Override
                    public void onError(Throwable e) {
                    }

                    @Override
                    public void onComplete() {

                    }
                });

这样好理解多了吧,因为p层用的Observable也事Model层返回的,所以实际上我们的网络请求是还在Model完成的。接着我们回到Presenter层去声明Model变量,实现剩余的方法


import com.example.tonjies.mvp_java_b.module.info.bean.Student;
import com.example.tonjies.mvp_java_b.module.info.model.InfoModel;
import com.example.tonjies.mvp_java_b.module.info.prsenter.contract.InfoContract;

import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;

/**
 * Created by 舍长 on 2019/1/4
 * describe:获取学生数据P层实现接口
 */
public class InfoPresenter implements InfoContract.InfoIPresenter {
    //声明View接口
    private InfoContract.infoView view;

    //声明Model变量
    private InfoModel infoModel;

    public InfoPresenter(InfoContract.infoView view) {
        this.view = view;
        infoModel = new InfoModel();
    }

    //获取学生数据
    @Override
    public void getData() {
        infoModel.getData()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer() {
                    //可以在这里拦截请求
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Student student) {
                        view.show("学生姓名:" + student.getName() + "学生年龄:" + student.getAge());
                    }

                    @Override
                    public void onError(Throwable e) {
                        view.show("获取失败" + e.getMessage());
                    }

                    //请求完成
                    @Override
                    public void onComplete() {
                        Log.d("helloWorld", "请求完成");
                    }
                });
    }
    
        //销毁View对象
    public void detachView() {
        infoView = null;
    }
}

最后在Activity去调用

/**
 * 获取学生信息Activity
 */
public class InfoActivity extends AppCompatActivity implements InfoContract.infoView{
    private Button button;

    //声明P层变量
    private InfoPresenter infoPresenter;

    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_info);
        infoPresenter=new InfoPresenter(this);
        button=findViewById(R.id.btn_01);//点击请求
        textView=findViewById(R.id.txt_01);//显示文本
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                infoPresenter.getData();//进行网络请求
            }
        });
    }

    /**
     * 在P层中回调的方法
     * @param msg
     */
    @Override
    public void show(String msg) {
        textView.setText("获取到的学生数据:"+msg);
    }

    /**
     * 销毁View对象
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        infoPresenter.detachView();
    }
}

最后不要忘了在权限菜单中设置第一启动项,以及网络权限

   
   

总结

RxJava,Retrofit,Mvp,不管单独哪一个,拿出来都感觉有点不好写。但是如果三个结合起来,再加上一些封装,就逐渐理解了,所以这三个哪一个都离不开

Mvp还是比较好理解,反而是RxJava和Retrofit学起来会难很多,特别是遇到问题时,比较难查找是什么原因,这里给出几个教程链接,都是前辈们写的很不错的文件

给初学者的RxJava2.0教程

Android Rxjava:这是一篇 清晰 & 易懂的Rxjava 入门教程

RxJava学习资源

这是一份很详细的 Retrofit 2.0 使用教程(含实例讲解)

Retrofit2 和 RxJava 配合使用时的错误处理

文章为了好理解,并没有对RxJava进行更深的封装,如果封装起来像

.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()),这样重复的代码就不用写了,可以去了解一下

另外如果你已经读完了两篇文章,你可以去找个小项目去练习一下,如果你没有特别好的主意,可以去看看我模仿郭神的天气项目做的一个Mvp小例子,教程

简单天气APP.gif

文章到这里就结束了,如果你觉得文本就你有所帮助,希望能帮忙点个喜欢,这对我来说是种很好的鼓励,

理直气壮

你可能感兴趣的:(带实际例子的Android架构MVP简述二「Java,MVP,Retrofit,RxJava,带Model」)