关于Android封装一个全局的BaseActivity你需要知道的

  • 1.前言
  • 2.特点
  • 3.代码及说明
    • 3.1.优缺点
    • 3.2.代码
    • 3.3.注意点
  • 4.总结
  • 5.最后

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;@Overrideprotected 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");}@Overrideprotected void onStart() {super.onStart();Log.e("app", this.getClass().getSimpleName() + "------onStart");}@Overrideprotected void onRestoreInstanceState(Bundle savedInstanceState) {super.onRestoreInstanceState(savedInstanceState);Log.e("app", this.getClass().getSimpleName() + "------onRestoreInstanceState");}@Overrideprotected void onRestart() {super.onRestart();Log.e("app", this.getClass().getSimpleName() + "------onRestart");}@Overrideprotected void onResume() {super.onResume();Log.e("app", this.getClass().getSimpleName() + "------onResume");}@Overrideprotected void onSaveInstanceState(Bundle outState) {super.onSaveInstanceState(outState);Log.e("app", this.getClass().getSimpleName() + "------onSaveInstanceState");}@Overrideprotected void onPause() {super.onPause();Log.e("app", this.getClass().getSimpleName() + "------onPause");}@Overrideprotected void onStop() {super.onStop();Log.e("app", this.getClass().getSimpleName() + "------onStop");}@Overrideprotected 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类主要是持有一些idpublic 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() {@Overridepublic void onClick(View v) {if (!AppUtils.isNotFastClick()) {return;}onNavigateUpClicked();}});}}//子类直接调用展示toastpublic 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() {@Overridepublic 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.总结

  • 不是很复杂,写的也比较详细,也基本适用于绝大部分的场景。可能还有其他需要注意的细节回头想起来再补上。
  • 最后附上一个自己在GitHub 的Android_Demo持续完善

5.最后

开通了个公众号,扫码关注一下,可以获得超过1个G的免费PDF书籍学习资料,并且可以及时收到我分享的内容哦!

关于Android封装一个全局的BaseActivity你需要知道的相关推荐

  1. 封装一个全局使用的二次确认弹窗

    背景: 如图所示,在项目中进行删除.取消.停用等等操作的时候,出于考虑误操作等,我们通常会需要用户进行二次确认,然后再进行操作.对于这种使用比较多的公共功能,我们如何才能保持一致并且简单的使用呢?出于 ...

  2. Android 封装一个通用的PopupWindow

    *本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 先上效果图: 完整代码地址已上传Github:CommonPopupWindow PopupWindow这个类用来实现一个弹出框, ...

  3. 微信小程序,分享如何封装一个全局支持暂停,拖动等各类操作的音视频等多媒体管理器

    不知不觉埋头于业务已许久,距离上一篇分享应该很久很久以前,具体何时,已无从知晓.慢慢的开始觉得锅有点热,感觉呼吸有点困难,温水里面的青蛙趁着腿还没完全麻木的时候,也想着开始重拾旧梦,稍微往上蹬蹬,好了 ...

  4. 封装一个全局邮箱提示后缀的组件

    一.在components新建mailbox.vue <template> <div> <el-form class="mailbox" :rules ...

  5. 使用反射+注解封装一个基于Sqlite极简的android数据库框架

    数据库 背景 GreenDao 封装 创建数据库 对象映射表 数据库操作 扩展 总结 背景 目前市面上已经有比较好用的数据库框架,比如GreenDao和OrmLite,而且功能也很齐全,那为什么还要多 ...

  6. android 全局 socket,Autobahn Android的一个应用示范和全局化

    先介绍下Autobahn Android是什么东西,简单来说,就是github上的一个开源项目,目的是在Android端实现WebSocket的协议,项目的地址在这里,看得懂源码的童鞋可以去看,地址点 ...

  7. android 播放器封装,Android视频播放最全总结:MediaPlayer+TextureView封装一个完美实现全屏、小窗视频播放器,附项目源码...

    原标题:Android视频播放最全总结:MediaPlayer+TextureView封装一个完美实现全屏.小窗视频播放器,附项目源码 作者:xiaoyanger 来源:http://www.jian ...

  8. 封装一个uniapp的全局弹窗组件,vue中也可以使用,在任何页面都可以弹出

    效果图: 场景: 当你对接websocket时,或者轮询也好,你需要获取到最新的信息,并且在任何页面弹出一个组件进行后续操作 思路: 1.先封装好要弹出的公共组件 2.向vue原型上挂载全局方法,拿到 ...

  9. 我的Android进阶之旅------gt;Android使用AlarmManager全局定时器实现定时更换壁纸

    该DEMO将会通过AlarmManager来周期的调用ChangeService,从而让系统实现定时更换壁纸的功能. 更换壁纸的API为android.app.WallpaperManager,它提供 ...

最新文章

  1. python udp client
  2. python 作用域 前缀_Python 之作用域和名字空间
  3. C++ Primer 5th笔记(6)chapter6 函数: 参数
  4. 笔记本8G+256G固态免费送,吃鸡不吃力,包邮!
  5. 深度解析K-L变换 及其 在特征识别中的应用
  6. 图文并茂重新认识下递归
  7. [2020-AAAI] Revisiting Image Aesthetic Assessment via Self-Supervised Feature Learning 论文简析
  8. 什么叫中断隐指令,具体做哪三件事呢?
  9. 收发一体超声波测距离传感器模块_超声波避障传感器在哪些地方运用
  10. 美国62%智能音箱用户都使用了语音购物,连鹦鹉都忍不住了
  11. Reactive Extensions入门(6):使用Rx进行单元测试
  12. 使用PHP中的curl发送请求
  13. 使用Thread包装类进行多线程操作
  14. Nginx 读写分离详解
  15. soapUI简单教程
  16. 三人表决器Verilog
  17. linux系统下安装wrk和使用
  18. 尚硅谷docker基础篇 2018版
  19. 如何用usb电缆连接到计算机,如何使用USB串行电缆将文件从计算机传输到树莓派...
  20. Visio工具的跨线解决问题

热门文章

  1. 苗圩:推动形成万物互联、天地一体的网络空间
  2. (八)操作系统-进程的状态与转换
  3. 服务代码 *99#、 *98*1# 、 *98*2#的区别
  4. 学习日记01 GEE下载Sentinel2A数据(外部导入shp和直接绘图)
  5. dropbox for android,将Dropbox for Android中的文件直接导出到SD卡 | MOS86
  6. js 获取url参数(函数封装)
  7. 地理坐标系、投影坐标系及对应WKIDW在生成缓冲区时的应用
  8. at定时任务,一次性定时计划任务
  9. excel 根据中文索引英文
  10. jsonpath介绍与使用