如何正确的写一个复杂的Activity ---- CommonMVPActivity

277 阅读4分钟

适用范围

当你的页面比较复杂,一两百行不能写完时,建议使用CommonMVPActivity 。

Github


先看示例代码如下:

TestActivity.java

请留意TestActivity,TestActivityBiz,TestActivityView三个类的继承。

  • initData -------> 在onCreate方法中执行,执行一次
  • initView -------> 在onCreate方法中执行,执行一次
  • loadData ------> 在onCreate方法中执行,执行一次
  • initListener ----> 在onCreate方法中执行,执行一次
package com.okaynaira.android.ui.activity.test;

import android.os.Bundle;

import com.okaynaira.android.R;
import com.okaynaira.android.databinding.ActivityTestBinding;

import leo.work.support.base.activity.mvp.ActivityBiz;
import leo.work.support.base.activity.mvp.ActivityView;
import leo.work.support.base.activity.mvp.CommonMVPActivity;

/**
 * ---------------------------------------------------------------------------------------------
 * 功能描述: 逻辑比较复杂的Activity,MVP架构
 * ---------------------------------------------------------------------------------------------
 * 时  间: 2021/12/21
 * ---------------------------------------------------------------------------------------------
 * 代码创建: 1613-3
 * ---------------------------------------------------------------------------------------------
 * 代码备注:
 * ---------------------------------------------------------------------------------------------
 **/
public class TestActivity extends CommonMVPActivity<TestActivity.TestActivityView, TestActivity.TestActivityBiz> {

    @Override
    protected TestActivityView createActivityView() {
        return new TestActivityView(this, R.layout.activity_test);
    }

    @Override
    protected TestActivityBiz createActivityBiz() {
        return new TestActivityBiz(this);
    }


    /*********************
     *     业      务    *
     *********************/
    public static class TestActivityBiz extends ActivityBiz<TestActivity> {

        /*********************
         *     全 局 变 量    *
         *********************/
        //.....
        public TestActivityBiz(TestActivity activity) {
            super(activity);
        }

        /*********************
         *  生 命 周 期 方 法  *
         *********************/

        @Override
        protected void initData(Bundle bundle) {

        }

        @Override
        protected void loadData(boolean isShowState, boolean isSaveLastData) {

        }

        /*********************
         *     业 务 方 法    *
         *********************/
        //.....

    }

    /*********************
     *     U        I    *
     *********************/
    public static class TestActivityView extends ActivityView<TestActivity, ActivityTestBinding> {

        /*********************
         *     全 局 变 量    *
         *********************/
        //.....
        public TestActivityView(TestActivity activity, int layoutId) {
            super(activity, layoutId);
        }

        /*********************
         *  生 命 周 期 方 法  *
         *********************/

        @Override
        protected void initView() {

        }

        @Override
        protected void initListener() {

        }

        /*********************
         *     业 务 方 法    *
         *********************/
        //.....

    }

}

CommonMVPActivity.java

package leo.work.support.base.activity.mvp;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import leo.work.support.support.common.LogUtil;


public abstract class CommonMVPActivity<V extends ActivityView, B extends ActivityBiz> extends AppCompatActivity {

    //Activity对象
    public Activity activity;
    //View对象
    public V activityView;
    //业务逻辑对象
    public B activityBiz;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LogUtil.e("=======================>" + this.getClass().getName());
        //竖屏
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        //
        activity = this;
        //
        activityView = createActivityView();
        //
        activityBiz = createActivityBiz();
        //初始化数据
        activityBiz.initData(savedInstanceState);
        //初始化View
        activityView.initView();
        //网络加载
        activityBiz.loadData(true, false);
        //监听加载
        activityView.initListener();
    }


    //View
    protected abstract V createActivityView();

    //逻辑
    protected abstract B createActivityBiz();

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

    @Override
    protected void onStart() {
        super.onStart();
        activityView.onStart();
        activityBiz.onStart();
    }

    @Override
    protected void onPause() {
        super.onPause();
        activityView.onPause();
        activityBiz.onPause();
    }

    @Override
    protected void onStop() {
        super.onStop();
        activityView.onStop();
        activityBiz.onStop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        activityView.onDestroy();
        activityBiz.onDestroy();
    }


    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        activityView.onRequestPermissionsResult(requestCode, permissions, grantResults);
        activityBiz.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        activityView.onActivityResult(requestCode, resultCode, data);
        activityBiz.onActivityResult(requestCode, resultCode, data);

    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        activityView.onNewIntent(intent);
        activityBiz.onNewIntent(intent);
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        activityView.onBackPressed();
        activityBiz.onBackPressed();
    }

    /**
     * 设置 app 不随着系统字体的调整而变化
     */
    @Override
    public Resources getResources() {
        Resources resources = super.getResources();
        Configuration config = new Configuration();
        config.setToDefaults();
        resources.updateConfiguration(config, resources.getDisplayMetrics());
        return resources;
    }

}

CommonMVPActivity讲解

  • CommonMVPActivity继承AppCompatActivity,本质上就是一个普通的Activity。
  • CommonMVPActivity主要持有了三个对象
    • Activity对象
    • ActivityView对象,所有的UI操作(设置文字,修改背景,隐藏显示...都写在这里)
    • Activity对象,所有的逻辑操作都写在这里(网络请求,数据库增删查改,各种业务逻辑...都写在这里)
  • 假设你需要点击按钮执行某个逻辑,你可以这么做
    • 1.ActivityView对象设置View的点击事件
    • 2.使用ActivityView的Activity对象,通过Activity对象拿到ActivityBiz对象,调用ActivityBiz对象的逻辑方法。例如:activity.activityBiz.xxxx();
  • 假设你执行某个逻辑后需要刷新UI,你可以这么做
    • 1.使用ActivityBiz的Activity对象,通过Activity对象拿到ActivityView对象,实现UI操作。例如:activity.activityView.xxxx();

ActivityView.java

package leo.work.support.base.activity.mvp;

import android.content.Intent;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;

/**
 * View
 *
 * @param <A>
 */
public abstract class ActivityView<A extends CommonMVPActivity, T extends ViewDataBinding> {

    public A activity;
    //ViewDataBinding
    public T binding;

    public ActivityView(A mActivity, int layoutId) {
        activity = mActivity;
        //设置布局
        activity.setContentView(layoutId);
        //ViewDataBinding
        binding = DataBindingUtil.setContentView(activity, layoutId);
    }


    //初始化View
    protected abstract void initView();

    //初始化监听事件
    protected abstract void initListener();


    public void onResume() {

    }

    public void onStart() {

    }

    public void onPause() {

    }

    public void onStop() {

    }

    public void onDestroy() {

    }

    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

    }


    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {

    }


    protected void onNewIntent(Intent intent) {

    }

    public void onBackPressed() {

    }
}

ActivityView讲解

这个类主要用于处理UI操作,文字,背景,图片输入框监听,点击事件,一系列单纯的和UI相关的操作,绝对不要写任何逻辑,比如网络请求,数据库操作,广播监听,权限开关。 ActivityView只负责设置UI,监听UI事件,把事件告诉Activity或者ActivityBiz。

  • ActivityView主要持有了两个对象
    • Activity对象。-------------------> 你可以通过Activity拿到ActivityBiz对象,实现UI ----> 业务的代码逻辑。
    • ViewDataBinding对象。--------> 你可以通过它调用你xml布局中所有的View。ViewDataBinding官方文档
  • initView,initListener两个方法在Activity的onCreate方法中被调用,执行一次,执行顺序自己看源码。
  • 剩下的onResume(),onStart()....onBackPressed()都是生命周期方法,方便你开发使用,不够自己再加。

ActivityBiz.java

package leo.work.support.base.activity.mvp;

import android.content.Intent;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/**
 * 数据与逻辑
 */
public abstract class ActivityBiz<A extends CommonMVPActivity> {

    public A activity;

    public ActivityBiz(A activity) {
        this.activity = activity;
    }

    protected abstract void initData(Bundle savedInstanceState);

    protected abstract void loadData(boolean isShowState, boolean isSaveLastData);

    public void onResume() {

    }

    public void onStart() {

    }

    public void onPause() {

    }

    public void onStop() {

    }

    public void onDestroy() {

    }

    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

    }


    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {

    }


    protected void onNewIntent(Intent intent) {

    }

    public void onBackPressed() {

    }

}

ActivityBiz讲解

这个类主要用于处理逻辑操作,网络请求,数据库增删查改,广播监听,服务启动,各种逻辑操作,一定不要写任何UI操作。 ActivityBiz只负责逻辑相关的操作。

  • ActivityBiz主要持有了一个对象
    • Activity对象。-------------------> 你可以通过Activity拿到ActivityView对象,实现业务 ----> UI的代码逻辑。
  • initData,loadData两个方法在Activity的onCreate方法中被调用,执行一次,执行顺序自己看源码。
  • 剩下的onResume(),onStart()....onBackPressed()都是生命周期方法,方便你开发使用,不够自己再加。

快速生成Activity的模板

  • 设置方式:

    image.png

    image.png

  • 模板内容:

    #if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
    
    import android.os.Bundle;
    
    import com.okaynaira.android.R;
    import com.okaynaira.android.databinding.ActivityTestBinding;
    
    import leo.work.support.base.activity.mvp.ActivityBiz;
    import leo.work.support.base.activity.mvp.ActivityView;
    import leo.work.support.base.activity.mvp.CommonMVPActivity;
    
    #parse("File Header.java")
    public class ${NAME} extends CommonMVPActivity<${NAME}.${NAME}View, ${NAME}.${NAME}Biz> {
    
        @Override
        protected ${NAME}View createActivityView() {
            return new ${NAME}View(this, R.layout.#if (${LAYOUT_NAME} && ${LAYOUT_NAME} != "")${LAYOUT_NAME}#end#if (${LAYOUT_NAME} && ${LAYOUT_NAME} == "")activity_#end);
        }
    
        @Override
        protected ${NAME}Biz createActivityBiz() {
            return new ${NAME}Biz(this);
        }
    
        /*********************
         *     业      务    *
         *********************/
        public static class ${NAME}Biz extends ActivityBiz<${NAME}> {
    
            /*********************
             *     全 局 变 量    *
             *********************/
            //.....
    
            public ${NAME}Biz(${NAME} activity) {
                super(activity);
            }
    
            /*********************
             *  生 命 周 期 方 法  *
             *********************/
    
            @Override
            protected void initData(Bundle bundle) {
    
            }
    
            @Override
            protected void loadData(boolean isShowState, boolean isSaveLastData) {
    
            }
    
            /*********************
             *     业 务 方 法    *
             *********************/
            //.....
    
        }
    
        /*********************
         *     U        I    *
         *********************/
        public static class ${NAME}View extends ActivityView<${NAME}, #if (${BINDING_NAME} && ${BINDING_NAME} != "")${BINDING_NAME}#end#if (${BINDING_NAME} && ${BINDING_NAME} == "")Activity(xxxBinding)#end> {
    
            /*********************
             *     全 局 变 量    *
             *********************/
            //.....
    
            public ${NAME}View(${NAME} activity, int layoutId) {
                super(activity, layoutId);
            }
    
            /*********************
             *  生 命 周 期 方 法  *
             *********************/
    
            @Override
            protected void initView() {
    
            }
    
            @Override
            protected void initListener() {
    
            }
    
            /*********************
             *     业 务 方 法    *
             *********************/
            //.....
    
        }
    
    }
    

注意点

在Activity开发过程中,请务必按照《Activity开发规范》进行开发。


感言

其实可以直接

  • 让ActivityView持有ActivityBiz对象
  • 让ActivityBiz持有ActivityView对象 但是经过考虑 还是不要这么做原因如下:
  • 害怕被滥用导致UI和逻辑又混在一起
  • 目前来说不影响功能,只是影响了代码的美观。