安卓MVP模式示例与使用方法

 一:概念

       MVC模式中Activity对应了MVC中的V和C,同时担任两个角色,会导致Activity过于复杂臃肿,因为MVC中是允许Model和View进行交互的,而MVP中很明显,Model与View之间的交互由Presenter完成。还有一点就是Presenter与View之间,Presenter与Model之间的交互是通过接口的方式来进行的。简而言之即Model层与View层不直接交互,而是通过Presenter来处理。Model层声明接口、View层声明接口提供给Presenter调用来间接实现M层与V层的交互,Presenter也提供一些方法供View、Model层调用

        MVP: 

                  Model:模型层,处理数据之类,如数据库操作,访问网络等。

                  View:视图层,xml布局文件及Activity、fragment。

                  Presenter:Presenter表示器(也称主持人),通过调用V、M层的接口来连接Model与View.

        MVC、MVP模式区别如下图所示:

                                                        

二:操作流程

        (示例项目结构

            (示例:点击按钮获取天气信息,然后显示在TextView中。


1.M层:

#声明接口来表示M层要执行的动作,如数据库的操作有存储数据和获取数据这两个操作,即可在接口中声明抽象方法来表示这些动作,如:

public interface IWeatherModel {
    public abstract void setInfo(String info);//设置数据
    public abstract String getInfo();//获取数据
}

#创建接口的实现类,重写接口中的抽象方法,在里面执行具体的操作。(Presenter会调用里面的方法)如:

public class WeatherModel implements IWeatherModel {
    private String mString;

    @Override
    public void setInfo(String info) {
        mString=info;
    }

    @Override
    public String getInfo() {
        return mString;
    }
}

 2.V层:

#(与M层类似)声明接口来表示View层要执行的动作,如下面这个界面:


它要执行的操作包括3个: &当点击按钮时出现正在加载的Toast。

                                        &当获取到天气信息之后将数据展示在TextView中。

                                        &数据获取成功后出现加载完成的Toast。

所以就声明一个接口并创建三个抽象方法来表示这些操作,如:

public interface IWeatherView {
    public abstract void showToast();
    public abstract void dismissToast();
    public abstract void setWeatherInfo(String info);
}

#创建接口的实现类(以上界面是看得见的,所以实现类是Activity,也可是fragment),重写接口中的抽象方法,在里面执行具体的操作。(Presenter会调用里面的方法)如:

public class MainActivity extends AppCompatActivity implements IWeatherView{//实现接口
    private Button mButton;
    private TextView mTextView;
    private WeatherPresenter mWeatherPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mButton=findViewById(R.id.button);
        mTextView=findViewById(R.id.textView);
        mWeatherPresenter=new WeatherPresenter(this);
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mWeatherPresenter.requestWeatherInfo();
            }
        });
    }

/*重写接口中的抽象方法*/<------这一步只需看这里
    @Override
    public void showToast() {//因为此方法在WeatherPresenter中是在子线程中调用的,所有要进行UI操作需回到UI线程。
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this,"正在加载···",Toast.LENGTH_SHORT).show();

            }
        });
    }

/*重写接口中的抽象方法*/<------这一步只需看这里
    @Override
    public void dismissToast() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this,"加载完成",Toast.LENGTH_SHORT).show();
            }
        });
    }

/*重写接口中的抽象方法*/<------这一步只需看这里
    @Override
    public void setWeatherInfo(final String info) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mTextView.setText(info);
            }
        });
    }
} 

3.P层:

#创建一个类作为Presenter,然后创建V、M层的接口的实现类的对象(也可叫做接口的引用,不能叫接口的对象,因为接口不能创建对象),以此来调用接口中的方法。如:

public class WeatherPresenter {<------这一步只需看这里
    private IWeatherView mIWeatherView;//接口的引用<------这一步只需看这里
    private IWeatherModel mIWeatherModel;//接口的引用<------这一步只需看这里

    public WeatherPresenter(IWeatherView mIWeatherView){<------这一步只需看这里
        this.mIWeatherView=mIWeatherView;//初始化接口的引用<------这一步只需看这里
        mIWeatherModel=new WeatherModel();//初始化接口的引用<------这一步只需看这里
    }

    public void requestWeatherInfo(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                mIWeatherView.showToast();
                try {
                    Thread.sleep(4000);
                    String info="21° 阴";
                    mIWeatherModel.setInfo(info);
                    String weather=mIWeatherModel.getInfo();
                    mIWeatherView.setWeatherInfo(weather);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    mIWeatherView.dismissToast();
                }
            }
        }).start();
    }
} 
上面代码:声明一个Presenter类的构造方法(如下面代码),在里面初始化接口的引用,因为要使用接口的方法,需创建接口的实现类的对象。至于构造方法中传入一个View层接口 IWeatherView的引用。是因为这里是MainActivity实现的View层的接口,所以无法创建Activity的对象,那么就在MainActivity中使用Presneter的构造方法并把this传入,这样Presneter类中就能初始化View层接口的引用。
public WeatherPresenter(IWeatherView mIWeatherView){
        this.mIWeatherView=mIWeatherView;
        mIWeatherModel=new WeatherModel();
    }

#可以在presenter类中提供一些方法供View层和Model层调用,如这里声明一个requestWeatherInfo方法(如下面代码),就是提供给MainActivity用的,当点击按钮时就从Model层中获取数据,而View层不能和Model层直接联系,所以通过Prenenter类中的方法间接与Model联系。

public void requestWeatherInfo(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                mIWeatherView.showToast();//调用View层的接口方法显示Toast
                try {
                    Thread.sleep(4000);
                    String info="21° 阴";//模拟访问网络获取天气数据
                    mIWeatherModel.setInfo(info);//调用Model层的方法存储数据
                    String weather=mIWeatherModel.getInfo();//调用Model层的方法获取数据
                    mIWeatherView.setWeatherInfo(weather);//调用View层的方法设置数据到TextView。
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    mIWeatherView.dismissToast();//调用View层的接口方法显示Toast
                }
            }
        }).start();
    } 

4:剩下的就是在接口的实现类中写具体操作的代码。

public class MainActivity extends AppCompatActivity implements IWeatherView{
    private Button mButton;
    private TextView mTextView;
    private WeatherPresenter mWeatherPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mButton=findViewById(R.id.button);
        mTextView=findViewById(R.id.textView);
        mWeatherPresenter=new WeatherPresenter(this);//创建Presenter类对象,以便在V层调用Presenter的方法,这里构造方法传入this。
        mButton.setOnClickListener(new View.OnClickListener() {//点击事件
            @Override
            public void onClick(View view) {
                mWeatherPresenter.requestWeatherInfo();//调用Presenter里面的方法。
            }
        });
    }

    @Override
    public void showToast() {//因为此方法在WeatherPresenter中是在子线程中调用的,所有要进行UI操作需回到UI线程。
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this,"正在加载···",Toast.LENGTH_SHORT).show();

            }
        });
    }

    @Override
    public void dismissToast() {//因为此方法在WeatherPresenter中是在子线程中调用的,所有要进行UI操作需回到UI线程。
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this,"加载完成",Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public void setWeatherInfo(final String info) {//因为此方法在WeatherPresenter中是在子线程中调用的,所有要进行UI操作需回到UI线程。
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mTextView.setText(info);
            }
        });
    }
}
 
public class WeatherModel implements IWeatherModel {
    private String mString;

    @Override
    public void setInfo(String info) {//存储数据,模拟数据库操作。
        mString=info;
    }

    @Override
    public String getInfo() {//获取数据
        return mString;
    }
}
(以上是自己的理解,可参考 这篇文章


      

猜你喜欢

转载自blog.csdn.net/LZK_Dreamer/article/details/79940778
今日推荐