프레임워크(1) - MVP 모델을 설명하는 로그인 예시 및 Google 공식 예시

이 기사 소개

안드로이드 개발에서는 요구사항을 정리한 후 바로 첫 번째 코드를 작성하는 것이 아니라 먼저 전체 프로젝트의 기술적 프레임워크를 설계해야 합니다. 이 글에서는 주로 로그인 예시와 구글을 통해 MVP 모델을 설명합니다. 공식적인 예.

목차

  • 기술 프레임워크 설계를 수행하는 이유는 무엇입니까?
  • MVP 모델
  • MVP 모델을 설명하기 위한 로그인 예시
  • Google 공식 사례에서는 MVP 모델을 설명합니다.
  • 소스코드 다운로드 주소

기술 프레임워크 설계를 수행하는 이유는 무엇입니까?

  • 모듈식 기능

    프로그램을 모듈화하십시오. 즉, 높은 내부 집합과 모듈 간의 낮은 결합으로 개발 효율성이 향상되고, 각 모듈이 자체 임무를 수행할 수 있게 되며, 코드의 가독성, 확장성, 유지 관리 용이성 및 보안이 향상됩니다.

  • 개발 효율성 향상

    여러 사람이 동일한 모듈을 공동으로 개발할 수 있으며, 인터페이스를 설계한 후 개발자는 특정 지점(뷰 디스플레이, 비즈니스 로직/데이터 처리)에만 집중하면 됩니다.

  • 테스트 효율성 향상

    테스트에 편리하며 각 모듈을 개별적으로 테스트할 수 있으므로 테스트하기 전에 모든 모듈을 완료할 필요는 없습니다.

  • 코드 유지관리성 향상

    문제가 속한 모듈을 신속하게 찾아 변경하고, 현재 모듈을 최소한으로 변경하여 다른 기능에 영향을 미치고, 동시 버그 발생을 줄이고, 테스트 작업량을 줄일 수 있습니다.

기억하세요: 디자인을 위해 디자인하지 마세요. 그렇지 않으면 개발량이 늘어나게 됩니다.
여기에 이미지 설명을 삽입하세요.

MVP 모델

정의

MVP는 Model-View-Presenter 모드를 의미하며 계층화된 애플리케이션 개발에 사용됩니다.

  • 모델(Model)
    모델은 애플리케이션 데이터 로직을 처리하는 데 사용되는 애플리케이션의 일부로, 일반적으로 모델 객체는 데이터베이스에 있는 데이터 및 비즈니스 로직에 접근하는 역할(예: 네트워크 서버에서 데이터를 가져와 처리하는 일)을 담당합니다. 및 데이터 변경 시 업데이트 제어 장치.

  • 보기 -
    보기는 인터페이스 콘텐츠 업데이트 및 검색, 사용자가 트리거한 이벤트 처리 등 인터페이스 표시를 처리하는 애플리케이션의 일부입니다.

  • 발표자(컨트롤러)
    컨트롤러는 모델과 뷰에 대해 작동합니다. 모델 객체에 대한 데이터 흐름을 제어하고 데이터가 변경되면 뷰를 업데이트합니다. 모델과 뷰를 분리합니다.

MVP 간의 통화 관계

M은 P를 호출하고, P는 M을 호출하고, M은 결과를 P로 반환하고, P는 결과를 V로 반환합니다. V는 M을 직접 사용할 수 없으므로 인터페이스와 비즈니스 로직 또는 데이터 처리가 완전히 분리됩니다.
여기에 이미지 설명을 삽입하세요.

MVP 모드 실행 순서

실행 순서는 3가지 상황으로 설명되며, 자세한 내용은 아래 그림을 참조하세요.
여기에 이미지 설명을 삽입하세요.

안드로이드 프로젝트에서 MVP의 역할 설명

여기에 이미지 설명을 삽입하세요.

실제 사례

MVP 모드에서 구현된 로그인 기능

로그인 기능 구현 인터페이스는 사용자 이름과 비밀번호를 입력한 후 이를 서버에서 얻은 시뮬레이션된 사용자 이름과 비교한 후 로그인 결과를 인터페이스에 반환합니다.
인터페이스는 다음과 같이 표시됩니다.
여기에 이미지 설명을 삽입하세요.
역할, 클래스 및 인터페이스 간의 해당 관계
여기에 이미지 설명을 삽입하세요.

함수 호출 프로시저
여기에 이미지 설명을 삽입하세요.코드

  • 인터페이스 보기
public interface IUserLoginView {
    
    
     void setSuccessInfo();
     void setErrorInfo(int iErrorCode);
}
  • XML 파일 보기
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="案例说明:"
        android:textColor="@android:color/holo_red_dark"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="登录功能的MVPDemo\n1、具体分为3层View-Presenter-Model\n2、V-P层传数据采用函数的参数传参\n3、M层模拟从网络获取数据。\n4、正确用户名和密码分别为:mvp,123456"
        android:textColor="@android:color/holo_red_dark"/>

    <EditText
        android:id="@+id/et_username"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="mvp" />

    <EditText
        android:id="@+id/et_pwd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="123456" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="Login"
        android:onClick="Login"/>
</LinearLayout>

  • 보기 활동
public  class LoginMVPDemoActivity extends AppCompatActivity implements IUserLoginView {
    
    
    private EditText etUserName;
    private EditText etPwd;

    IUserLoginPresenter bUserLoginPresenter = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login_mvpdemo);

        etUserName = (EditText) findViewById(R.id.et_username);
        etPwd = (EditText) findViewById(R.id.et_pwd);

        bUserLoginPresenter = new UserLoginPresenter(this);
    }

    @Override
    public void setSuccessInfo() {
    
    
        Toast.makeText(this,"登录成功!",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void setErrorInfo(int iErrorCode) {
    
    
        if(iErrorCode == 1){
    
    
            Toast.makeText(this,"登录失败:用户名不存在或不正确",Toast.LENGTH_SHORT).show();
        }else if(iErrorCode == 2){
    
    
            Toast.makeText(this,"登录失败:密码不正确",Toast.LENGTH_SHORT).show();
        }

    }

    public void Login(View v){
    
    
        bUserLoginPresenter.login(etUserName.getText().toString(),
                etPwd.getText().toString());
    }
}

  • 발표자 인터페이스-IUserLoginPresenter
public interface IUserLoginPresenter {
    
    
     void login(String username, String strPwd);
}
  • 발표자 인터페이스-OnUserLoginListener
public interface OnUserLoginListener {
    
    
     void onUserLoginSuccess();
     void onUserLoginError(int iErrorCode);
}
  • 발표자 구체적인 수업
public class UserLoginPresenter implements IUserLoginPresenter,OnUserLoginListener{
    
    
    IUserLoginMode bUserLoginMode = null;
    IUserLoginView bUserLoginView = null;
    public UserLoginPresenter(IUserLoginView bUserLoginView){
    
    
        bUserLoginMode = new UserLoginMode();
        this.bUserLoginView = bUserLoginView;
    }

    @Override
    public void onUserLoginSuccess() {
    
    
        bUserLoginView.setSuccessInfo();
    }

    @Override
    public void onUserLoginError(int iErrorCode) {
    
    
        bUserLoginView.setErrorInfo(iErrorCode);
    }

    @Override
    public void login(String username, String strPwd) {
    
    
        bUserLoginMode.handleLogin(username,strPwd,this);
    }
}
  • 모델 인터페이스
public interface IUserLoginMode {
    
    
     void handleLogin(String username, String strPwd,
                            OnUserLoginListener bOnUserLoginListener);
}
  • 모델 구현 클래스
public class UserLoginMode implements IUserLoginMode {
    
    
    @Override
    public void handleLogin(String username, String strPwd,
                            OnUserLoginListener bOnUserLoginListener) {
    
    
        String s_username = "mvp";
        String s_strPwd ="123456";
        //用户名不存在
        if(!username.equals(s_username)){
    
    
            bOnUserLoginListener.onUserLoginError(1);
        } else if(username.equals(s_username) && s_strPwd.equals(strPwd)){
    
    
            bOnUserLoginListener.onUserLoginSuccess();
        }else if(username.equals(s_username) && !s_strPwd.equals(strPwd)){
    
    
            //密码不正确
            bOnUserLoginListener.onUserLoginError(2);
        }

    }
}

Google 공식 MVP데모

공식 데모는 데이터 로딩 프로세스의 처리를 구현하며, 인터페이스는 데이터 로딩이 시작되고, 데이터가 로딩되고, 데이터 로딩이 완료되어 인터페이스에 표시된다는 것을 보여줍니다.
인터페이스는 다음과 같이 표시됩니다.
여기에 이미지 설명을 삽입하세요.
공식 데모와 로그인 사례의 차이점

  • 모델은 인터페이스를 추상화하지 않고 직접 구체적으로 구현합니다.
  • v와 p 사이에 계약을 추가합니다. v와 p의 원래 인터페이스는 접촉의 두 인터페이스로 분류됩니다. v와 p 인터페이스를 기반으로 기본 v 인터페이스와 p 인터페이스를 추상화하여 v와 p 사이의 결합을 더 낮게 만듭니다. ., 프로그램의 확장성과 유지 관리성이 향상됩니다.

역할, 인터페이스, 클래스 간의 대응 함수
여기에 이미지 설명을 삽입하세요.
호출 프로세스
여기에 이미지 설명을 삽입하세요.

  • 인터페이스 보기
public interface BaseView<T> {
    
    
    void setPresenter(T presenter);
}
  • 발표자 인터페이스
public interface BasePresenter {
    
    
    void start();
}
  • 계약 인터페이스
public interface UserInfoContract {
    
    

    interface View extends BaseView<Presenter>{
    
    

        void showLoading();//展示加载框

        void dismissLoading();//取消加载框展示

        void showUserInfo(UserInfoModel userInfoModel);//将网络请求得到的用户信息回调

        String loadUserId();//假设接口请求需要一个userId
    }

    interface Presenter extends BasePresenter {
    
    
        void loadUserInfo();
    }

}
  • 보기-XML
<?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">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="案例说明:"
        android:textColor="@android:color/holo_red_dark"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Google官方提供的MVPDemo\n1、具体分为4View-Crontract-Presenter-Model\n2、contract层处于V层和P层中间,实现了原本在V层和P层的两个接口,V层和P层的接口是在Contract中对应接口的基础上再抽象一层,
使V层和P层的耦合性更低,灵活性更高。\n3、V-P层传参采用接口函数传参\n4、此Demo重点在于V层和P层的分离,M层的较少。"
        android:textColor="@android:color/holo_red_dark"/>

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="Hello World!" />

    <TextView
        android:id="@+id/tv_age"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

    <TextView
        android:id="@+id/tv_address"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />
</LinearLayout>

  • 보기 활동
public class GoogleMVPDemoActivity extends AppCompatActivity implements UserInfoContract.View {
    
    
    private TextView tv_name;
    private TextView tv_age;
    private TextView tv_address;

    private UserInfoContract.Presenter presenter;

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

        tv_name = (TextView) findViewById(R.id.tv_name);
        tv_age = (TextView) findViewById(R.id.tv_age);
        tv_address = (TextView) findViewById(R.id.tv_address);
        //通知P层要
        new UserInfoPresenter(this);
        presenter.start();
    }

    @Override
    public void showLoading() {
    
    
        Toast.makeText(this, "正在加载", Toast.LENGTH_LONG).show();
    }

    @Override
    public void dismissLoading() {
    
    
        Toast.makeText(this, "加载完成", Toast.LENGTH_LONG).show();
    }

    @Override
    public void showUserInfo(UserInfoModel userInfoModel) {
    
    
        if (userInfoModel != null) {
    
    
            tv_name.setText(userInfoModel.getName());
            tv_age.setText(String.valueOf(userInfoModel.getAge()));
            tv_address.setText(userInfoModel.getAddress());
        }
    }

    @Override
    public String loadUserId() {
    
    
        return "1000";//假设需要查询的用户信息的userId是1000
    }

    @Override
    public void setPresenter(UserInfoContract.Presenter presenter) {
    
    
        this.presenter = presenter;
    }
}
  • 발표자 구체적인 수업
ublic class UserInfoPresenter implements UserInfoContract.Presenter {
    
    
    private UserInfoContract.View view;

    public UserInfoPresenter(UserInfoContract.View view) {
    
    
        this.view = view;
        view.setPresenter(this);
    }

    @Override
    public void loadUserInfo() {
    
    
        String userId = view.loadUserId();
        view.showLoading();//接口请求前显示loading
        //这里模拟接口请求回调-
        new Handler().postDelayed(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                //模拟接口返回的json,并转换为javaBean
                UserInfoModel userInfoModel = new UserInfoModel("小宝", 1, "杭州");
                view.showUserInfo(userInfoModel);
                view.dismissLoading();
            }
        }, 3000);
    }

    @Override
    public void start() {
    
    
        loadUserInfo();
    }

}
  • 모델 구체적인 클래스
public class UserInfoModel {
    
    
    private String name;
    private int age;
    private String address;

    public UserInfoModel(String name, int age, String address) {
    
    
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }

    public String getAddress() {
    
    
        return address;
    }

    public void setAddress(String address) {
    
    
        this.address = address;
    }
}

요약하다

코드를 분석할 때 두 케이스 MVP 간의 객체 보유, 객체 전송 및 데이터 전송 방식(메서드 매개변수 전달 및 메소드 매개변수 전달)에 주의하세요.

사례 다운로드 주소

MVPDemo 다운로드 주소

참고 링크

MVC, MVP, MVVM 패턴 그림: 명확하게 알 수 있도록 설명하는 예

추천

출처blog.csdn.net/li1500742101/article/details/105382015