软件编程
位置:首页>> 软件编程>> Android编程>> 详解Android封装一个全局的BaseActivity

详解Android封装一个全局的BaseActivity

作者:还吹着风、  发布时间:2022-09-16 07:05:23 

标签:Android,封装,BaseActivity

1.前言

  • 对于一个Android开发者来说,每一个页面都继承一个单独的系统Activity,有时候会带来很多不必要的困扰。比如:每一个页面会有重复的代码,阅读起来麻烦;每一次写新的页面功能总要打开原来的页面代码拷贝一部分过来;有时候代码调试排查问题也不方便等等。

  • 如果你的项目里面没有将Activity都继承自一个自己封装的BaseActivity、或者针对自己封装的BaseActivity觉得还不够完善的,这篇博客可能会对你有帮助!

2.特点

  • 封装:将所有Activity都用到的一部分代码封装到一个统一管理的Activity类(后面全部起名叫BaseActivity),然后由这个BaseActivity继承自Android系统的AppCompatActivity(一般是这个)。

  • 继承:页面上用到的Activity都继承自我们的自己BaseActivity,BaseActivity封装的方法在Activity内直接调用。

3.代码及说明

3.1.优缺点

  • 优点:减少了代码的重复,提高了写代码的效率、以及提高了代码的维护性

  • 缺点:不要任何代码都放在BaseActivity,那样可能会导致BaseActivity过于臃肿,不利于代码的阅读和维护,甚至出现App奔溃

下面会讨论哪些代码应该放在BaseActivity里面,哪些需要谨慎

3.2.代码

下面我贴一份我自己封装的BaseActivity,在代码中和代码下面做了解释:


public abstract class BaseActivity extends AppCompatActivity {

public Activity mActivity;
   private Unbinder mUnbinder;
   private static float sNoncompatDensity;
   private static float sNoncompatScaledDensity;
   private MaterialDialog mDialog;

@Override
   protected void onCreate(@Nullable Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       onAdjustLayout();
       setContentView(setContentLayout());
       //这里的是初始化绑定ButterKnife,在onDestory做了销毁
       mUnbinder = ButterKnife.bind(this);
       this.mActivity = this;
       //统一将一个activity添加到一个集合里面
       AppManager.getInstance().addActivity(mActivity);
       initToolBar();
       initPresenter();
       initData(savedInstanceState);
       Log.e("app", this.getClass().getSimpleName() + "------onCreate");
   }

@Override
   protected void onStart() {
       super.onStart();
       Log.e("app", this.getClass().getSimpleName() + "------onStart");
   }

@Override
   protected void onRestoreInstanceState(Bundle savedInstanceState) {
       super.onRestoreInstanceState(savedInstanceState);
       Log.e("app", this.getClass().getSimpleName() + "------onRestoreInstanceState");
   }

@Override
   protected void onRestart() {
       super.onRestart();
       Log.e("app", this.getClass().getSimpleName() + "------onRestart");
   }

@Override
   protected void onResume() {
       super.onResume();
       Log.e("app", this.getClass().getSimpleName() + "------onResume");
   }

@Override
   protected void onSaveInstanceState(Bundle outState) {
       super.onSaveInstanceState(outState);
       Log.e("app", this.getClass().getSimpleName() + "------onSaveInstanceState");
   }

@Override
   protected void onPause() {
       super.onPause();
       Log.e("app", this.getClass().getSimpleName() + "------onPause");
   }

@Override
   protected void onStop() {
       super.onStop();
       Log.e("app", this.getClass().getSimpleName() + "------onStop");
   }

@Override
   protected void onDestroy() {
       super.onDestroy();
       onDestroyActivity();
       mUnbinder.unbind();
       Log.e("app", this.getClass().getSimpleName() + "------onDestroy");
   }

/**
    * 显示一个Fragment
    */
   public void showFragment(Fragment fragment) {
       if (fragment != null && fragment.isHidden()) {
           FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
           fragmentTransaction.show(fragment);
           fragmentTransaction.commit();
       }
   }

/**
    * 隐藏一个Fragment
    */
   public void hideFragment(Fragment fragment) {
       if (fragment != null && !fragment.isHidden()) {
           FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
           fragmentTransaction.hide(fragment);
           fragmentTransaction.commit();
       }
   }

//这是一个设置toolbar标题栏的方法,ToolBarOptions类主要是持有一些id
   public void setToolBar(int toolBarId, ToolBarOptions options) {
       Toolbar toolbar = findViewById(toolBarId);
       if (options.titleId != 0) {
           toolbar.setTitle(options.titleId);
       } else {
           toolbar.setTitle("");
       }
       if (!TextUtils.isEmpty(options.titleString)) {
           toolbar.setTitle(options.titleString);
       }
       if (options.backgroundColor != 0) {
           toolbar.setBackgroundResource(options.backgroundColor);
       }
       if (options.logoId != 0) {
           toolbar.setLogo(options.logoId);
       }
       setSupportActionBar(toolbar);

if (options.isNeedNavigate) {
           toolbar.setNavigationIcon(options.navigateId);
           toolbar.setContentInsetStartWithNavigation(0);
           toolbar.setNavigationOnClickListener(new View.OnClickListener() {
               @Override
               public void onClick(View v) {
                   if (!AppUtils.isNotFastClick()) {
                       return;
                   }
                   onNavigateUpClicked();
               }
           });
       }
   }

//子类直接调用展示toast
   public void showToast(String s) {
       ToastUtil.showToast(this, s);
   }

//给子类提供一个获取activity对象的方式
   public Activity getActivity() {
       return this;
   }

//一个弹窗loading库 github地址:
   //implementation 'com.afollestad.material-dialogs:core:0.9.6.0'
   public void showLoading(String loadDesc) {
       mDialog = new MaterialDialog.Builder(this)
               .progress(true, -1)
               .content(loadDesc)
               .canceledOnTouchOutside(false)
               .cancelable(false)
               .show();
   }

public void showLoading(int resId) {
       mDialog = new MaterialDialog.Builder(this)
               .progress(true, -1)
               .content(getString(resId))
               .canceledOnTouchOutside(false)
               .cancelable(false)
               .show();
   }

public void showLoading() {
       mDialog = new MaterialDialog.Builder(this)
               .progress(true, -1)
               .content("加载中...")
               .canceledOnTouchOutside(false)
               .cancelable(false)
               .show();
   }

public void hideLoading() {
       if (mDialog != null) {
           mDialog.dismiss();
       }
   }

//这里是退出app相关的逻辑,可以根据自己的退出做具体的处理
   public void exitLogin() {
       SharedPreferenceUtils.getInstance(mActivity).put(Constant.KEY_LOGIN_TOKEN, "");
       if (mDialog != null) {
           mDialog.hide();
           mDialog = null;
       }
       mDialog = new MaterialDialog.Builder(this)
               .canceledOnTouchOutside(false)
               .title("提示")
               .content("账号已在其他地方登录,请退出重新登录!")
               .positiveText("确定")
               .onPositive(new MaterialDialog.SingleButtonCallback() {
                   @Override
                   public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                       AppManager.getInstance().finishAllActivity();
                       Intent intent = new Intent(mActivity, LoginActivity.class);
                       startActivity(intent);
                       finish();
                   }
               }).show();
   }

private void onNavigateUpClicked() {
       onBackPressed();
   }

//开始contentLayout前调整布局(子类若有需要可以单独复写)
   public void onAdjustLayout() {

}

//下面这5个方法是子类必须实现的,分别是layout布局、toolbar、mvp的persenter初始化、
//onCreate内的initData、以及页面销毁的onDestroyActivity(可以根据自己的需要添加)
   public abstract int setContentLayout();

public abstract void initToolBar();

public abstract void initPresenter();

public abstract void initData(Bundle savedInstanceState);

public abstract void onDestroyActivity();
}

3.3.注意点

  • 在BaseActivity的每个生命周期内都有log日志,这里是方便观察执行到activity的哪个生命周期,logcat也可以简单封装一下,统一控制日志是否打印。

  • BaseActivity并不适合每一个页面的Activity,比如进入应用的闪屏页面,就可以考虑不继承BaseActivity,因为这个页面通常不需要写太多代码。或者还有其他特殊的业务场景下。

  • 需要注意一个Dialog弹窗问题,在BaseActivity里面,每次show一个dialog的时候我都是创建一个新的对象,那么就要注意dialog在未关闭之前不能再去show,否则可能会导致dialog出现异常。但是不要在onDestory方法里面去隐藏dialog弹窗,因为在A页面进入B页面的时候,会先执行到B页面生命周期的onCreate、onStart、onResume三个方法,然后再执行A页面的onStop可能还有onDestory方法,所以等B页面加载完成再去销毁A页面是错误的。

  • 有时候为了方便可能有人会把请求Android中权限检测的方法放在BaseActivity里面,这样并不是特别合适,因为所有继承自BaseActivity的页面都会去检测权限,这样会导致用户体验差,所以建议用到权限的地方再去请求,最好自己封装一个工具类,用起来方便一点。

  • BaseActivity的封装并不强求子类必须实现activity生命周期相关的方法,除了几个抽象方法(我认为子类需要复写的,可以根据业务自己定),必要的话可以自己复写。

4.总结

不是很复杂,写的也比较详细,也基本适用于绝大部分的场景。可能还有其他需要注意的细节回头想起来再补上。

来源:https://blog.csdn.net/fanhenghao/article/details/115511240

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com