zoukankan      html  css  js  c++  java
  • MVP应用在android app上

          使用MVP模式来解耦activity中业务代码和界面代码。在activity中,将其中的业务抽象到presenter层;将其中的界面代码抽象到View层。

          

          MVP模式:

          

            一个软件被划分成三层,View层,Presenter层,Model层。

            View层的职责是展示界面,界面绘制。

            Presenter层的职责是,实现各种业务逻辑,业务逻辑的代码都放在这一层。

            Model层的职责是数据的存储,修改,获取。

            各层之间的交互:

            View层和Presenter层之间的通信是双向的。

            Presenter层和Model层之间的通信是双向的。

            View层不与Model层发生交互。

           

           MVP模式应用到Android app:

           View层:activity,fragment,其中的界面展示,就是View层的内容。

           Presenter层:点击一个按钮要执行的业务逻辑,则是由Presenter层来实现。也就是说,Presenter层抽象,提取出activity,fragment中的业务逻辑。这样就可以将业务逻辑代码与界面展示代码解耦掉。可以重用业务逻辑。

          Model层:这一层,则是数据存取,数据修改层。配置信息,获取数据源的数据,获取服务器数据,获取数据库的数据,更新数据库的数据,这些实现代码都由这一层来提供。

         MVP模式应用到Android app的一个例子分析:  

    例子分析:
     
    1.每个层要做的事情,用接口声明好。
    2.接口声明好之后,就用实际的类来实现。
     
    比如登陆界面:
    1.要确定出登陆界面,它的View有哪些行为。
    2.登陆界面的业务逻辑实现,是通过调用presenter层的方法来进行的。
    3.presenter与view之间是相互通信的。
     

    Login这个模块,把View层和presenter层放在了一起:

    package com.antonioleiva.mvpexample.app.Login;

    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.EditText;
    import android.widget.ProgressBar;

    import com.antonioleiva.mvpexample.app.R;
    import com.antonioleiva.mvpexample.app.main.MainActivity;

    public class LoginActivity extends Activity implements LoginView, View.OnClickListener {

        private ProgressBar progressBar;
        private EditText username;
        private EditText password;
        private LoginPresenter presenter;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_login);

            progressBar = (ProgressBar) findViewById(R.id.progress);
            username = (EditText) findViewById(R.id.username);
            password = (EditText) findViewById(R.id.password);
            findViewById(R.id.button).setOnClickListener(this);

            presenter = new LoginPresenterImpl(this);
        }

        @Override public void showProgress() {
            progressBar.setVisibility(View.VISIBLE);
        }

        @Override public void hideProgress() {
            progressBar.setVisibility(View.GONE);
        }

        @Override public void setUsernameError() {
            username.setError(getString(R.string.username_error));
        }

        @Override public void setPasswordError() {
            password.setError(getString(R.string.password_error));
        }

        @Override public void navigateToHome() {
            startActivity(new Intent(this, MainActivity.class));
            finish();
        }

        @Override public void onClick(View v) {
            presenter.validateCredentials(username.getText().toString(), password.getText().toString());
        }

    }       

    一、View层和presenter的交互:
     
    View到presenter的调用(View--->presenter):
    上述代码,当用户点击按钮的时候,会执行一个账号和密码验证的业务逻辑。这个业务逻辑是封装在presenter中的。我们调用presenter的validateCredentials方法,传递参数,就可以执行账号和密码验证的业务逻辑。
     
    将业务逻辑封装到presenter层的好处是,我们可以在任何地方重用一个业务逻辑。比如,这个validateCredentials的业务逻辑,就可以被重用。
     
    presenter到View的调用(presenter--->view):
    在实例化presenter的时候,要提供一个LoginView的实现。
     public LoginPresenterImpl(LoginView loginView) {
            this.loginView = loginView;
            this.loginInteractor = new LoginInteractorImpl();
        }
    然后,LoginView接口定义了各种行为。presenter通过调用LoginView提供的行为,来实现presenter对View的控制。
    在这里,进行验证的时候,会有不同的情况,针对不同的情况,presenter层会调用LoginView中不同的方法,来告知用户当前的验证结果。
    如下:
     @Override public void onUsernameError() {
            loginView.setUsernameError();
            loginView.hideProgress();
        }
     
      @Override public void onPasswordError() {
            loginView.setPasswordError();
            loginView.hideProgress();
        }
     
       @Override public void onSuccess() {
            loginView.navigateToHome();
        }
     
    1).presenter层的业务逻辑实现:
    Presenter层只有一个业务逻辑,它由接口LoginPresenter接口声明:
    public interface LoginPresenter {
        public void validateCredentials(String username, String password);
    }
     
    public class LoginPresenterImpl implements LoginPresenter, OnLoginFinishedListener {

        private LoginView loginView;
        private LoginInteractor loginInteractor;

        public LoginPresenterImpl(LoginView loginView) {
            this.loginView = loginView;
            this.loginInteractor = new LoginInteractorImpl();
        }

        @Override public void validateCredentials(String username, String password) {
            loginView.showProgress();
            loginInteractor.login(username, password, this);
        }

        @Override public void onUsernameError() {
            loginView.setUsernameError();
            loginView.hideProgress();
        }

        @Override public void onPasswordError() {
            loginView.setPasswordError();
            loginView.hideProgress();
        }

        @Override public void onSuccess() {
            loginView.navigateToHome();
        }
    }
    它的业务逻辑实现是由成员loginInterator来做的。
    然后,loginInterator要将判断结果通知LoginPresenterImpl,它通过调用OnLoginFinishedListener的接口中的方法。LoginPresenterImpl实现了OnLoginFinishedListener接口。
     
    通信由LoginInteratorImpl到LoginPresenterImpl(LoginInteratorImpl--->LoginPresenterImpl):
    OnLoginFinishedListener接口,定义了LoginPresenterImpl可以被LoginInteratorImpl调用的行为,用来告知LoginPresenterImpl验证的结果。
    public interface OnLoginFinishedListener {

        public void onUsernameError();

        public void onPasswordError();

        public void onSuccess();
    }
     
    public class LoginInteractorImpl implements LoginInteractor {

        @Override
        public void login(final String username, final String password, final OnLoginFinishedListener listener) {
            // Mock login. I'm creating a handler to delay the answer a couple of seconds
            new Handler().postDelayed(new Runnable() {
                @Override public void run() {
                    boolean error = false;
                    if (TextUtils.isEmpty(username)){
                        listener.onUsernameError();
                        error = true;
                    }
                    if (TextUtils.isEmpty(password)){
                        listener.onPasswordError();
                        error = true;
                    }
                    if (!error){
                        listener.onSuccess();
                    }
                }
            }, 2000);
        }
    }  
    通信由LoginPresenterImpl到LoginInteratorImpl(LoginPresenterImpl--->LoginInteratorImpl):
        @Override public void validateCredentials(String username, String password) {
            loginView.showProgress();
            loginInteractor.login(username, password, this);
        }
     
    二、View层:
    当前的Activity实现了LoginView接口,那么当前Activity是是LoginView,作为View层。
    它定义了供presenter调用的行为。
    public interface LoginView {
        public void showProgress();

        public void hideProgress();

        public void setUsernameError();

        public void setPasswordError();

        public void navigateToHome();
    }
    ---------------------------------------------------------------------
    Main模块
     
     
    一、View层:
    public interface MainView {

        public void showProgress();

        public void hideProgress();

        public void setItems(List<String> items);

        public void showMessage(String message);
    }
    这些是供presenter层调用的方法。
    这些方法中的代码是跟界面展示有关的。
     
    View层到Presenter层的通信,及View层的实现:
    public class MainActivity extends Activity implements MainView, AdapterView.OnItemClickListener {

        private ListView listView;
        private ProgressBar progressBar;
        private MainPresenter presenter;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            listView = (ListView) findViewById(R.id.list);
            listView.setOnItemClickListener(this);
            progressBar = (ProgressBar) findViewById(R.id.progress);
            presenter = new MainPresenterImpl(this);

        }

        @Override protected void onResume() {
            super.onResume();
            presenter.onResume();
        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
            if (id == R.id.action_settings) {
                return true;
            }
            return super.onOptionsItemSelected(item);
        }

        @Override public void showProgress() {
            progressBar.setVisibility(View.VISIBLE);
            listView.setVisibility(View.INVISIBLE);
        }


        @Override public void hideProgress() {
            progressBar.setVisibility(View.INVISIBLE);
            listView.setVisibility(View.VISIBLE);
        }


        @Override public void setItems(List<String> items) {
            listView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items));
        }


        @Override public void showMessage(String message) {
            Toast.makeText(this, message, Toast.LENGTH_LONG).show();
        }


        @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            presenter.onItemClicked(position);
        }
    }
     
    红色部分是MainView的行为,都是界面展示方面的代码。
    蓝色部分,是View层到Presenter通信的实现(View--->Presenter)。
     
    二、Presenter层:
    public interface MainPresenter {

        public void onResume();

        public void onItemClicked(int position);
    }
    它有两个业务逻辑要实现,一个是onResume(),一个是onItemClicked(int position)。
     
    Presenter层到View层的通信,及Presenter层的实现:
    public class MainPresenterImpl implements MainPresenter, OnFinishedListener {

        private MainView mainView;
        private FindItemsInteractor findItemsInteractor;

        public MainPresenterImpl(MainView mainView) {
            this.mainView = mainView;
            findItemsInteractor = new FindItemsInteractorImpl();
        }

        @Override public void onResume() {
            mainView.showProgress();
            findItemsInteractor.findItems(this);
        }

        @Override public void onItemClicked(int position) {
            mainView.showMessage(String.format("Position %d clicked", position + 1));
        }

        @Override public void onFinished(List<String> items) {
            mainView.setItems(items);
            mainView.hideProgress();

        }
    }
    红色部分是Presenter层到View层的通信实现(Presenter--->View)。
    onResume()方法和onItemClicked(int position)方法是Presenter实现的业务逻辑。
    其中FindItemsInteractor成员,负责创建一个List的实现。
     
    参考资料:
     http://antonioleiva.com/mvp-android/
  • 相关阅读:
    Java学习二十九天
    Java学习二十八天
    47. Permutations II 全排列可重复版本
    46. Permutations 全排列,无重复
    subset ii 子集 有重复元素
    339. Nested List Weight Sum 339.嵌套列表权重总和
    251. Flatten 2D Vector 平铺二维矩阵
    217. Contains Duplicate数组重复元素
    209. Minimum Size Subarray Sum 结果大于等于目标的最小长度数组
    438. Find All Anagrams in a String 查找字符串中的所有Anagrams
  • 原文地址:https://www.cnblogs.com/ttylinux/p/4483288.html
Copyright © 2011-2022 走看看