这篇博客主要是从BaseActivity与BaseFragment的封装开始,总结我们在实战开发中关于Fragment的注意事项以及心得体会。

先看以下效果图:

这里模拟的是用户登录模块,你可能会说,很普通的效果嘛,这有啥。嘿嘿,那我要告诉你的是,这么多模块仅仅由两个Activity构成的。等你从头到尾看完这篇博客,你就会惊叹其中的奥秘了。废话不多说,开始。

本案例属于多模块Activity+多Fragment,下面简单介绍下概念。

多模块Activity+多Fragment 是开发APP非常适合的架构,相对于多Activity,这种架构APP占用内存降低,性能提升;相对于单Activity+多Fragment,这种开发起来逻辑相对简单,不容易出错。

对于多模块Activity+多Fragment,这里有两个概念需要我们了解一下:

  • 同级式Fragment: 比如QQ的主界面,消息,联系人,动态,这三个Fragment就属于同级关系,我们平时项目中主界面的Fragment也是属于同级Fragment
  • 流程式Fragment:比如我这个示例Demo,可以理解为用户账户流程,可以包括:登录/注册模块—-忘记/找回密码模块—-用户协议模块,这些Fragent就是属于流程式Fragment

我的示例Demo使用的是流程式Fragment,结合今天的主题—-BaseActivity与BaseFragment的封装,我们一探究竟。

BaseActivity的封装

首先看一下代码:

  1. 两个必须实现的抽象方法,获取布局文件Layout的resource ID,获取布局文件中Fragment的ID

  2. 添加fragment:开启一个事物,替换了当前layout容器中的由getFragmentContentId()标识的fragment。通过调用 addToBackStack(String tag), replace事务被保存到back stack, 因此用户可以回退事务,并通过按下BACK按键带回前一个fragment,如果没有调用 addToBackStack(String tag), 那么当事务提交后, 那个fragment会被销毁,并且用户不能导航回到它。其中参数tag将作为本次加入BackStack的Transaction的标志。commitAllowingStateLoss(),这种提交是允许发生异常时状态值丢失的情况下也能正常提交事物

  3. 移除fragment:与addToBackStack()相对应的接口方法是popBackStack(),调用该方法后会将事务操作插入到FragmentManager的操作队列,轮询到该事务时开始执行。这里进行了一下判断,获取回退栈中所有事务数量,大于1的时候,执行回退操作,等于1的时候,代表当前Activity只剩下一个Fragment,直接finish()当前Activity即可

  4. 监听返回键的返回事件,当事务数量等于1的时候,直接finish()

进一步封装AppActivity

  1. 一个必须实现的抽象方法来获取当前Activity应该显示的第一个Fragment
  2. 获取intent的方法,在需要传递/接受数据的Activity实现
  3. 在Activity的onCreate()方法中拿到intent,添加fragment

不过这样的封装是需要制定一个布局文件的,activity_base.xml布局文件代码为:

BaseFragment的封装

在APP运行在后台的时候,系统资源紧张的时候会导致后台的Activity被销毁,可能会带来一些问题,其中之一就是Fragment调用getActivity()的地方却返回null,报了空指针异常。

解决办法就是在Fragment基类里设置一个Activity mActivity的全局变量,在onAttach(Activity activity)里赋值,使用mActivity代替getActivity()。

封装后的使用

BaseActivity与BaseFragment的封装都已经完成,接下来就是具体在项目中的使用了,这里分两种情况。

  • 第一种情况:没有参数的传递

示例Demo中的主界面MainActivity,可以看到代码相当的精简,对应的MainFragment代码如下:

很简单的业务逻辑,点击第一个按钮跳转到LoginActivity,点击第二个按钮跳转到注册模块,布局文件代码就不贴了。

  • 第二种情况:有参数的传递

可以看到,LoginActivity与之前不一样的是,重写了handleIntent()这个方法来获取传递过来的数据,重要的一点,创建Fragment的时候传递了一个参数。 代码很简单,即通过Arguments传递参数。

给Fragment添加newInstance方法,将需要的参数传入,设置到bundle中,然后setArguments(bundle),最后在onCreate中进行获取。

这种使用arguments来创建Fragment的方法,强烈推荐使用:

这样就完成了Fragment和Activity间的解耦,使用Fragment的一个很大的原因,就是为了复用。这一点在我主界面点击第二个按钮跳转到注册界面有所体现

对Fragment传递数据,建议使用setArguments(Bundle args),而后在onCreate中使用getArguments()取出,在 内存不足导致异常时,系统会帮你保存数据,不会造成数据的丢失。和Activity的Intent原理一致。

使用newInstance(参数) 创建Fragment对象,优点是调用者只需要关系传递的哪些数据,而无需关心传递数据的Key是什么。

其他界面大同小异,大家可以在此自由发挥。关于流程式Fragment,就先到这里,看看同级式Fragment应该注意的问题。

hide()与show()导致的Fragment重叠

同级式Fragment在内存不足导致的异常情况下,会出现重叠现象,处理方法是在基类的Activity中onSaveInstanceState()内保存当前所在Fragment的tag或者下标,在onCreate()是恢复的时候,隐藏其它Fragment。

假设我们存在三个同级Fragment,目前Fragment为ContactFragment,此时切换到后台,由于内存因素导致Activity重建,我们就可以通过上述代码解决Fragment重叠以及回到ContactFragment页面。

当然要记得在onSaveInstanceState存储下当前页面信息

推荐阅读

参考链接

从BaseActivity与BaseFragment的封装谈起

BaseActivity与BaseFragment的封装的更多相关文章

  1. Android 谈谈封装那些事 --BaseActivity 和 BaseFragment(二)

      1.前言 昨天谈了BaseActivity的封装,Android谈谈封装那些事--BaseActivity和BaseFragment(一)有很多小伙伴提了很多建议,比如: 通用标题栏可以自定义Vi ...

  2. Basefragment的封装使用

    1.前言 封装作为面向对象的三大特性之一,在我们平时的coding过程用的那是非常的多的.大多数时候,我们可以根据封装情况评判代码的质量水平. 本文主要讲解的是fragment的封装.大体上,在项目的 ...

  3. android手机安全卫士、Kotlin漫画、支付宝动画、沉浸状态栏等源码

    Android精选源码 轻量级底部导航栏   android手机卫士源码   android实现高仿今日头条源码   一个用Kotlin写的简单漫画App源码   android吐槽项目完整源码   ...

  4. 总结界面框架_UI_Adapter

    本人定期更新经典案例及解决方案如有疑问请联系我QQ1822282728 -- 277627117   下面是常用到的ui  Demo 安卓三级筛选菜单listview(非常经典) http://dow ...

  5. MVP+Dagger2+Rxjava+Retrofit+GreenDao 开发的小应用,包括新闻、图片、视频3个大模块,代码封装良好

    练习MVP架构开发的App,算是对自己学过的知识做一个总结,做了有一段时间,界面还算挺多的.代码量还是有的,里面做了大量封装,总体代码整理得非常干净,这个我已经尽力整理了. 不管是文件(java.xm ...

  6. Android 开发框架介绍

    一.概述 现android开发有很多开发框架使用,做App不一定用到框架,但好框架的思想也是值得学习.选择合适的开发框架可提供实用功能,简化项目开发提升效率. 二.Afinal框架 简介 Afinal ...

  7. 设计模式--装饰者设计模式(Decorator)

    装饰者模式又叫包装模式. 通过另一个对象来扩展自己的行为,在不破坏类的封装的情况下,实现松耦合,易扩展的效果.   抽象组件角色: 一个抽象接口,是被装饰类和装饰类的父接口可以给这些对象动态地添加职责 ...

  8. ProgressWheelDialogUtil【ProgressWheel Material样式进度条对话框】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 简单封装网络请求时的加载对话框以及上传.下载文件的进度加载对话框. 效果图 代码分析 ProgressWheel : 自定义view ...

  9. 【转】Android开发规范

    转自:https://github.com/Blankj/AndroidStandardDevelop 摘要 1 前言 2 AS 规范 3 命名规范 4 代码样式规范 5 资源文件规范 6 版本统一规 ...

随机推荐

  1. Java初学(六)

    一.final(最终)可以修饰类.方法.变量 特点:final修饰类,该类不能被继承 final修饰方法,该方法不能被重写(覆盖.重载.复写)        final修饰变量,该变量不能被重新赋值. ...

  2. linux 软件安装

    A:RPM包,这种软件包就像windows的EXE安装文件一样,各种文件已经编译好,并打了包,哪个文件该放到哪个文件夹,都指定好了,安装非常方便,在图形界面里你只需要双击就能自动安装,如果在命令行模式 ...

  3. include(thinkphp常用内置标签)

    变量输出使用普通标签就足够了,但是要完成其他的控制.循环和判断功能,就需要借助模板引擎的标签库功能了,系统内置标签库的所有标签无需引入标签库即可直接使用. XML标签有两种,包括闭合标签和开放标签,一 ...

  4. http https 区别

    HTTPS和HTTP的区别 一.https协议需要到ca申请证书,一般免费证书很少,需要交费.  二.http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议.  三. ...

  5. 让VisualVM+BTrace进入unsafe mode

    让VisualVM+BTrace进入unsafe mode http://kenai.com/projects/btrace/pages/UserGuide BTrace很强大,但有很多安全限制,比如 ...

  6. linux 下安装开发组件包

    最初安装redhat 时, 系统自己装的,只安装了base 包,在开发过程中,需要不停的安装某个需求包,   图省事,安装光盘下的开发组件包: 在安装光盘下,,,用命令: yum grouplist ...

  7. dns (域名系统)

    dns (域名系统) DNS(Domain Name System,域名系统),因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP ...

  8. 最长不下降子序列(LIS)

    最长上升子序列.最长不下降子序列,解法差不多,就一点等于不等于的差别,我这里说最长不下降子序列的. 有两种解法. 一种是DP,很容易想到,就这样: REP(i,n) { f[i]=; FOR(j,,i ...

  9. 【原创】express3.4.8源码解析之路由中间件

    前言 注意:旧文章转成markdown格式. 跟大家聊一个中间件,叫做路由中间件,它并非是connect中内置的中间件,而是在express中集成进去的. 显而易见,该中间件的用途就是 ------ ...

  10. 记Flume-NG一些注意事项(不定时更新,欢迎提供信息)

    这里只考虑flume本身的一些东西,对于JVM.HDFS.HBase等得暂不涉及.... 一.关于Source: 1.spool-source:适合静态文件,即文件本身不是动态变化的: 2.avro ...