【android】应用架构一一一一一Activity和Fragment的对比分析

2024-06-09 22:58

本文主要是介绍【android】应用架构一一一一一Activity和Fragment的对比分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这里主要就是讨论一个应用程序的UI组件,是全用Activity还是全用Fragment,或者是二者皆有,以及使用Activity和Fragment的一些注意事项。

 

Activity or Fragment

从API 11,Honeycomb开始,Google在Android之中加入了Fragment,一个轻量级的,可复用的,模块化的UI组件,并且官方也极力的推荐要尽可能的使用Fragment实现UI,尽量避免使用Activity,但是官方并没有详尽的解析为什么要这样做,因此,引发了很多人的困惑和网络上的争论

一些讨论

StackOverflow上面有很多类似的讨论,比如这个和这个,以及这篇博客和这篇。

总体的来讲,也都是推荐使用Fragment,并尽可能的使用Fragment,除非你必须使用Activity,否则就使用Fragment。

主要的区别

要想真正的理解什么时候该用Activity什么时候该用Fragment,就要从根本上理解它们之间到底有什么区别,以及各自所能做的事情:

Activity的优缺点

Activity是Android系统的四大核心组件之一,是唯一用户可见的组件,是可视化应用程序的基础,同时也是应用程序的主要入口。 它的优点是:

  • 方便使用,简单,没有版本限制
  • 可以处理系统相关的事情,比如窗体管理,对话框管理,与第三方应用交互,作为应用的入口,处理系统事件等
  • 生命周期简单明了
  • 不同的Activity实例的生命周期相互独立
  • 有系统的ActivityManager来管理,创建和维护实例,以及栈

Activity的缺点:

  • 无法完全的控制,创建和各种状态全部由Frameworks操控
  • 过于庞大和复杂
  • 传递参数相当费劲
  • launchMode和栈的管理过于复杂,让人捉摸不透

所以,因为它有缺点,所以它适合做为第一级组件,而不适合到处都用。也因此有了Fragment的诞生。

Fragment的优缺点

Fragment号称是轻量级的Activity,它有着Activity的部分功能,比如有生命周期,可以显示UI元素,可以有控制逻辑,它有很多优点:

  • 可以像普通对象那样自由的创建和控制
  • 因为可以得到实例,所以传递参数等会更加的容易和方便
  • 不用处理系统相关的事情
  • 显示方式可控制,替换,还是层叠,部分还是整体,都容易控制
  • 进出动画都相对容易

可以看出Fragment是实现可复用的,模块化UI的良好组件,熟悉iOS开发的人应该知道,这个Fragment跟iOS中的UIViewController是很相似的,都是MVC模式中的负责协调和控制的Controller。

实用的建议

那么,到此,我想我们应该能够总结出,到底什么时候该用Activity,什么时候该用Fragment了:

  • 一个应用程序必须至少要有一个Activity
  • 如果你需要开放入口给第三方应用,那么要用Activity。比如原生应用中的联系人,信息,相机,图库等,因为要留有接口给第三方使用,所以要用Activity。这也是所谓的组件级复用。
  • 如果要处理系统相关的事情,需要用Activity,比如横竖屏,语言变化,键盘等
  • 如果非要在横屏或竖屏显示,也要用Activity
  • 如果感觉用Fragment来做有很多的不方便,或者很困难,出于各种原因吧。

除此外,就使用Fragment吧。因此,对于一个应用程序的UI架构就是一个Host的Activity+Fragment的方式来做。

使用Activity时的注意事项

Activity是学习Android开发的第一堂课,我相信有过Android开发经验的人对Activity必定非常的熟悉了,对于使用Activity要注意:

  • 除非特别需要,否则要声明configChagnes,至少orientation和keyboard以及keyboardHidden需要加上
  • 减小对Activity实例的引用,尽可能用getApplication()或者getApplicationContext()来做为平台接口需要的Context参数
  • 在AndroidManifest.xml的activity标签中声明全屏,透明或者没有TitleBar的属性,而不是在onCreate()中去requestWindowFeature。除非你需要动态控制
  • Activity之间传递参数用Intent,尽量传基本数据类型和数据及ArrayList,和平台提供的数据类型如Uri。对于简单的POD(Plain Old Datastructure)数据类型,可以直接由基本数据组成,不必声明对象。对于有必要存在的对象,可以实现Parcelable接口,以方便在Activity之间传递。

使用Fragment时的注意事项

Fragment是由FragmentManager来管理的,每一个Activity有一个FragmentManager,管理着一个Fragment的栈,所以,Activity是系统级别的,由系统来管理ActivityManager,栈也是系统范围的。而Fragment则是每个Activity范围内的。

  • 同一个Activity中,只能有一个ID或TAG标识的Fragment实例。

    这很容易理解,同一个范围内,有标识的实例肯定是要唯一才行(否则还要标识干嘛)这个在布局中经常犯错,在布局中写Fragment最好不要加ID或者TAG,否则很容易出现不允许创建的错误。我的原则是如果放在布局中,就不要加ID和TAG;如果需要ID和TAG就全用代码控制。创建新实例前先到FragmentManager中查找一番,这也正是有标识的意义所在。

  • 一个Activity中有一个Fragment池,实例不一定会被销毁,可能会保存在池中。这个跟第一点差不多。就好比系统会缓存Activity的实例一样,FragmentManager也会缓存Fragment实例,以方便和加速再次显示。

  • 如前所述,FragmentManager的作用范围是整个Activity,所以,某一个布局ID,不能重复被Fragment替换。

    通常显示Fragment有二种方式,一种是层叠到某个布局上,或者把某个布局上面的Fragment替换掉,但是这个布局不能出现二次,比如布局A中有ID为id的区域,要显示为Fragment,此布局A,只能在一个Activity中显示一个,否则第二个id区域不能被Fragment成功替换。因为虽有二个ID布局的实例,但ID是相同的,对FragmentManager来说是一样的,它会认为只有一个,因为它看的是布局的ID,而不是布局的实例。

  • Fragment的生命周期反应Activity的生命周期。

    Fragment在显示和退出时会走一遍完整的生命周期。此外,正在显示时,就跟Activity的一样,Activity被onPause,里面的Fragment就onPause,以此类推,由此带来的问题就是,比如你在onStart()里面做了一些事情,那么,当宿主Activity被挡住,又出现时(比如接了个电话),Fragment的onStart也会被高到,所以你要想到,这些生命周期不单单在显示和退出时会走到。

  • Fragment的对用户可见性。

    这个问题出现在有Fragment栈的时候,也就是说每个Fragment不知道自己是否真的对用户可见。比如现在是Fragment A,又在其上面显示了Fragment B,当B显示后,A并不知道自己上面还有一个,也不知道自己对用户不可见了,同样再有一个C,B也不知。C退出后,B依然不知自己已在栈顶,对用户可见,B退后,A也不知。也就是说Fragment显示或者退出,栈里的其他Fragment无法感知。这点就不如Activity,a被b盖住后,a会走到onStop(),同样c显示后,b也能通过onStop()感知。Fragment可以从FragmentManager监听BackStackState的变化,但它只告诉你Stack变了,不告诉你是多了,还是少,还有你处的位置。有一个解决方案就是,记录页面的Path深度,再跟Fragment所在的Stack深度来比较,如果一致,那么这个Fragment就在栈顶。因为每个页面的Path深度是固定的,而Stack深度是不变化的,所以这个能准确的判断Fragment是否对用户可见,当然,这个仅针对整个页面有效,对于布局中的一个区域是无效的。

  • Fragment的事件传递。

    对于层叠的Fragment,其实就相当于在一个FrameLayout里面加上一堆的View,所以,如果处于顶层的Fragment没处理点击事件,那么事件就会向下层传递,直到事件被处理。比如有二个Fragment A和B,B在A上面,B只有一个简单的TextView且没处理事件,那么点击B时,会发现A里的View处理了事件。这个对于Activity也不会发生,因为事件不能跨窗体传播,上面的Activity没处理事件,也不会传给下面的Activity,即使它可见。解决之法,就是让上面的Fragment的根布局吃掉事件,为每个根ViewGroup添加onClick=“true”。

  • 与第三方Activity交互。与第三方交互,仍要采用Android的标准startActivityForResult()和onActivityResult()这二个方法来进行。但对于Fragment有些事情需要注意,Fragment也有这二个方法,但是为了能正确的让Fragment收到onActivityResult(),需要:

    1. 宿主Activity要实现一个空的onActivityResult(),里面调用super.onActivityResult()
    2. 调用Fragment#startActivityForResult()而不是用Activity的 当然,也可以直接使用Activity的startActivityForResult(),那样的话,就只能在宿主Activity里处理返回的结果了。

转自:http://www.toughcoder.net/blog/2014/10/22/effective-android-ui-architecture/

这篇关于【android】应用架构一一一一一Activity和Fragment的对比分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1046537

相关文章

在Ubuntu上部署SpringBoot应用的操作步骤

《在Ubuntu上部署SpringBoot应用的操作步骤》随着云计算和容器化技术的普及,Linux服务器已成为部署Web应用程序的主流平台之一,Java作为一种跨平台的编程语言,具有广泛的应用场景,本... 目录一、部署准备二、安装 Java 环境1. 安装 JDK2. 验证 Java 安装三、安装 mys

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链

Redis主从复制实现原理分析

《Redis主从复制实现原理分析》Redis主从复制通过Sync和CommandPropagate阶段实现数据同步,2.8版本后引入Psync指令,根据复制偏移量进行全量或部分同步,优化了数据传输效率... 目录Redis主DodMIK从复制实现原理实现原理Psync: 2.8版本后总结Redis主从复制实

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

锐捷和腾达哪个好? 两个品牌路由器对比分析

《锐捷和腾达哪个好?两个品牌路由器对比分析》在选择路由器时,Tenda和锐捷都是备受关注的品牌,各自有独特的产品特点和市场定位,选择哪个品牌的路由器更合适,实际上取决于你的具体需求和使用场景,我们从... 在选购路由器时,锐捷和腾达都是市场上备受关注的品牌,但它们的定位和特点却有所不同。锐捷更偏向企业级和专

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

java中VO PO DTO POJO BO DO对象的应用场景及使用方式

《java中VOPODTOPOJOBODO对象的应用场景及使用方式》文章介绍了Java开发中常用的几种对象类型及其应用场景,包括VO、PO、DTO、POJO、BO和DO等,并通过示例说明了它... 目录Java中VO PO DTO POJO BO DO对象的应用VO (View Object) - 视图对象

什么是 Ubuntu LTS?Ubuntu LTS和普通版本区别对比

《什么是UbuntuLTS?UbuntuLTS和普通版本区别对比》UbuntuLTS是Ubuntu操作系统的一个特殊版本,旨在提供更长时间的支持和稳定性,与常规的Ubuntu版本相比,LTS版... 如果你正打算安装 Ubuntu 系统,可能会被「LTS 版本」和「普通版本」给搞得一头雾水吧?尤其是对于刚入

TP-LINK/水星和hasivo交换机怎么选? 三款网管交换机系统功能对比

《TP-LINK/水星和hasivo交换机怎么选?三款网管交换机系统功能对比》今天选了三款都是”8+1″的2.5G网管交换机,分别是TP-LINK水星和hasivo交换机,该怎么选呢?这些交换机功... TP-LINK、水星和hasivo这三台交换机都是”8+1″的2.5G网管交换机,我手里的China编程has

Go信号处理如何优雅地关闭你的应用

《Go信号处理如何优雅地关闭你的应用》Go中的优雅关闭机制使得在应用程序接收到终止信号时,能够进行平滑的资源清理,通过使用context来管理goroutine的生命周期,结合signal... 目录1. 什么是信号处理?2. 如何优雅地关闭 Go 应用?3. 代码实现3.1 基本的信号捕获和优雅关闭3.2