Android Fragment★★

2023-05-16

1.Fragment

fragment译为“碎片”,是Android 3.0(API 11)提出的,最开始是为了适配大屏的平板。

Fragment看起来和Activity一样,是一个用户界面。可以结合多个Fragment到一个activity中来构建一个有多方面功能的UI,还可以重用同一个Fragment在多个activity中。Fragment可以当成是activity的一个组件,每个Fragment有单独的生命周期,可以在activity运行时进行添加和移除。因此,相比较于activity,Fragment更加轻量级,更加灵活。

一个Fragment总是被植入到一个activity中 ,并且它的生命周期受该activity直接影响,比如activity处于暂停,则其中的Fragment都暂停;activity销毁,则所有Fragment都销毁。但是,当一个activity运行时,你可以独立的操作每一个Fragment,比如添加和删除它们。进行类似的操作时,可以将Fragment添加到被activity管理的后退栈中,这样用户可以通过点击返回按钮来返回之前打开的Fragment。

Fragment可以作为activity的一部分添加到布局文件中,通过声明元素作为ViewGroup的一部分。也可以将Fragment作为一个没有自己UI的不可见的activity的工人。

总结一下:

①Fragment依赖于Activity,不能独立存在。

②一个Activity里可以有多个Fragment。

③一个Fragment可以被多个Activity重用。

③Fragment有自己的生命周期,并能接收输入事件。

④可以在Activity运行时动态地添加或删除Fragment。

 

2.Fragment生命周期

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5a2f6Iqz6Iqz,size_20,color_FFFFFF,t_70,g_se,x_16

 常见的周期流程:

①Activity加载Fragment的时候,依次调用:onAttach() -> onCreate() -> onCreateView() -> onActivityCreated() -> onStart() ->onResume()

②当做出一个悬浮的对话框风格的Activity或者其他,就是让Fragment所在的Activity可见,但不获得焦点:onPause()

③当对话框关闭,Activity又获得了焦点: onResume()

当替换Fragment,并调用addToBackStack()将它添加到后退栈中:onPause() -> onStop() -> onDestoryView() 。注意,此时的Fragment还没有被销毁。

⑤当按下键盘的回退键,Fragment会再次显示出来:onCreateView() -> onActivityCreated() -> onStart() -> onResume()

⑥如果替换后,在事务commit之前没有调用addToBackStack()方法将Fragment添加到后退栈中,或者退出了Activity,那么Fragment将会被完全结束,进入销毁状态: onPause() -> onStop() -> onDestoryView() -> onDestory() -> onDetach()

 

3.Fragment创建

①静态加载--以<fragment>标签的形式添加到Activity的布局中。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5a2f6Iqz6Iqz,size_20,color_FFFFFF,t_70,g_se,x_16

 1)定义Fragment的布局,即fragment的布局文件

2)自定义一个Fragment类,需要继承Fragment或它的子类,重写onCreateView()方法,在该方法中调用inflater.inflate()方法加载Fragment的布局文件,接着返回加载的view对象。

public class Fragmentone extends Fragment {

    @Override

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        if(view == null) {

            View view = inflater.inflate( R.layout.fragment1, container,false);

        }

        return view;

    }

}

3)在需要加载Fragment的Activity对应的布局文件中添加fragment标签,注意name属性是全限定类名,即包含Fragment的包名。

4)Activity在onCreate( )方法中调用setContentView()加载布局文件。

②动态加载--通过java代码将fragment添加到已存在的宿主Activity中

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5a2f6Iqz6Iqz,size_20,color_FFFFFF,t_70,g_se,x_16

动态添加fragment常用的类:

FragmentManager:用来管理Activity中的fragment,app包中使用getFragmentManager() ,v4包中使用getSupportFragmentManager。可以通过findFragmentById获取指定的Fragment,可以调用popBackStack()方法弹出后台Fragment,还可以调用addToBackStack()方法加入栈,或监听后台栈的变化:addOnBackStackChangeListener。

FragmentTransaction:事务,用来添加、移除、替换fragment,记得在操作完后要用commit()提交事务。

FragmentTransaction transaction = fm.benginTransatcion();//开启一个事务

transaction.add();往Activity中添加一个Fragment

transaction.remove();从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈,这个Fragment实例将会被销毁。

transaction.replace():使用另一个Fragment替换当前Fragment,实际上就是remove()然后add()的合体。

transaction.hide();隐藏当前的Fragment,仅仅是设为不可见,并不会销毁。

transaction.show():显示之前隐藏的Fragment。

transaction.commit():提交一个事务。

detach():将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护。

注意:在用fragment的时候,可能会经常遇到Activity状态不一致:State loss这样的错误。主要是因为:commit方法一定要在Activity.onSaveInstance()之前调用。

这些基本是操作Fragment的所有方式了,在一个事务开启到提交可以进行多个添加、移除、替换等操作。

注意:使用Fragment,一定要清楚这些方法,哪个会销毁视图,哪个会销毁实例,哪个仅仅只是隐藏,这样才能更好的使用它们。

attach():重建view视图,附加到UI上并显示。

1)比如:在FragmentA中的EditText填了一些数据,当切换到FragmentB时,如果希望回到A还能看到数据,则使用的就是hide和show。也就是说,希望保留用户操作的面板可以使用hide和show,当然了不要使劲在那new实例,进行下非null判断。

2)再比如:不希望保留用户操作,可以使用remove(),然后add();或者使用replace()这个和remove、add是相同的效果。

3)remove和detach有一点细微的区别:在不考虑回退栈的情况下,remove会销毁整个Fragment实例,而detach则只是销毁其视图结构,实例并不会被销毁。那么二者怎么取舍使用呢?如果当前Activity一直存在,在不希望保留用户操作的时候,可以优先使用detach。

 

4.Fragment与Activity的交互

1)组件获取

Fragment获得Activity中的组件: getActivity().findViewById(R.id.list);

Activity获得Fragment中的组件(根据id和tag都可以):getFragmentManager.findFragmentByid(R.id.fragment1);

2)数据传递

①Activity传递数据给Fragment

采用Bundle方式:在activity中创建Bundle数据包,把要传的值存入bundle,调用Fragment实例的setArguments(bundle)从而将Bundle数据包传给Fragment,然后Fragment中调用getArguments获得Bundle对象,进行解析就可以了。

举个例子:动态添加fragment的时候,在添加每个fragment之前,使用Bundle传输数据给每个fragment。

mManager = getSupportFragmentManager();

mTransaction = mManager.beginTransaction();

homeFragment = new HomeFragment();

//创建Bundle对象,并存储数据

Bundle bundle=new Bundle();

bundle.putString("home","Home");

homeFragment.setArguments(bundle);

fragment中接收数据:

Bundle bundle = this.getArguments();

String home = bundle.getString("home");

②Fragment传递数据给Activity

采用接口回调方式:在Fragment中定义一个内部回调接口,再让包含该Fragment的Activity实现该回调接口,Fragment就可以通过回调接口传数据了。

首先在Fragment 中定义一个回调接口:

public interface ICallBack{  

    public void getResult(String result);  

}  

并在Fragment中设置接口回调的方法:

public void getData(ICallBack callBack){  

    String msg = editText.getText().toString();  

    callBack.getResult(msg);  

}  

最后在Activity中回调:

leftFragment.getData(new ICallBack() {  

   @Override  

   public void getResult(String result) { 

        Toast.makeText(this, result, 1).show();  

    }

}); 

③Fragment与Fragment之间的数据互传

不同fragment之间的通信要依靠activity来完成。可以看成Fragment->Activity->Fragment,因为两个或多个fragment依附于同一个activity,所以完全可以通过把值传递到共同依附的Activity,然后通过Bundle传给另一个fragment。

方式一:先调用findFragmentById()方法根据id获得fragment对象,然后调用fragment中的方法进行赋值。

manager.findFragmentById(); //根据ID找到对应的Fragment实例,主要用在静态添加fragment的布局中,因为静态添加的fragment才会有ID

manager.findFragmentByTag();//根据TAG找到对应的Fragment实例,主要用于在动态添加的fragment中,根据TAG找到fragment实例

manager.getFragments();//获取所有被ADD进Activity中的Fragment

然后,直接在一个Fragment中调用另外一个Fragment的公开方法,前提是要先拿到另外一个Fragment的实例。

一般情况下,都是动态添加Fragment的,所以通过在add每个Fragment的时候,给每个Fragment设置个tag。

manager = this.getSupportFragmentManager();

transaction = manager.beginTransaction();

LeftFragment leftFragment = new LeftFragment();

RightFragment rightFragment = new RightFragment();

transaction.add(R.id.left, leftFragment, "left");

transaction.add(R.id.right, rightFragment, "right");

transaction.commit();

在Activity创建的时候,添加上所有的fragment,并为每个fragment设置tag,这样才会在每个fragment中通过findFragmentByTag()时不会出现空指针。

在LeftFragment中:

RightFragment rightFragment = (RightFragment) getActivity().getSupportFragmentManager().findFragmentByTag("right");

if (rightFragment == null) return;

rightFragment .setTextView("right now");

这样就实现了在LeftFragment里给RightFragment传值的效果。

这种方式是两个fragment直接通信的。(不推荐使用)

方式二:通过接口回调的方法实现两个fragment之间的通信

比如点击MessageFragment的Button按钮,给CommunityFragment中的TextView传递数据,就需要在MessageFragment中定义接口,并定义回调的方法,该方法的参数中传一个String字符串。接着让附属Activity实现这个接口并重写回调方法,也就得到了传过来的数据,然后通过findFragmentByTag()的方法获取要传给的CommunityFragment的实例。

在CommunityFragment中定义一个方法用来接收这个数据,然后用对象直接调用这个方法将参数传递给这个方法就可以了。

方式三:其他方式

EventBus:使用方便,但其使用的是反射原理,会有稍微的延迟,并且他人维护不方便;

static静态变量:使用方便,但是每个static变量都会占用一块内存区,Android系统分配给每个App的内存是有限的(63M),过多很容易造成App内存溢出;

广播Broadcast Receiver:Android的广播是有限制的,除了系统的广播外,其他的广播尽量少用。另外,广播会有延迟;

接口:接口是常用的Fragment之间的通讯方式,通过一个主Activity作为通讯桥梁(谷歌官方声明:两个Fragment之间永远不要直接通讯),实现两个Fragment之间的通讯。

接口的方式是推荐的,但是,传统的接口方式会造成一些问题,如果主Activity实现了多个Fragment的通讯回调接口,那就需要implements很多接口,类中还要实现一大堆接口的方法,显得有点繁琐。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android Fragment★★ 的相关文章

  • 设置文本视图 Android 的文本颜色

    在 string xml 文件中我使用以下标签
  • Cheesesquare:enterAlways 会产生错误的布局

    Adding enterAlways到 Cheesesquare 演示的滚动标志
  • 如何在android中显示保存在sdcard文件夹中的图像[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 当我正在显
  • Recyclerview 动态部分不使用任何第三个库

    我想将标头添加到 recyclerview 我正在尝试使用来实现它 Override public int getItemViewType int position depends on your problem if position 0
  • 将现有 VARCHAR 列与 Room 结合使用

    我正在尝试将现有的数据库与 Android Room 一起使用 但是 我的一个表有一个 VARCHAR 列 Room 似乎只支持 TEXT 不支持 VARCHAR 而且 sqlite 不允许修改列类型 那么 有没有办法使用Room中现有的带
  • 通过 WhatsApp 发送消息

    由于我发现了一些较旧的帖子 表明 Whatsapp 不支持此功能 我想知道是否发生了变化 以及是否有办法打开与我通过意图发送的号码进行 Whatsapp 聊天 UPDATE请参阅https faq whatsapp com en andro
  • Dialog.setTitle 不显示标题

    我正在尝试向我的对话框添加自定义标题 但是每当我运行我的应用程序时 它都不会显示标题 我创建对话框的代码是 final Dialog passwordDialog new Dialog this passwordDialog setCont
  • ExoPlayer2 - 如何使 HTTP 301 重定向工作?

    我开始使用 ExoPlayer 来传输一些音频 一切都很顺利 直到我遇到一个带有 301 永久移动 重定向的 URL ExoPlayer2 默认情况下不处理该问题 我已经看过这个线程 https github com google ExoP
  • OnLongClickListener 不工作

    我有一个ImageView 我需要使用onLongClickListener对于图像视图 当我使用这段代码时 什么也没有发生 Code gallery Gallery findViewById R id gall1 gallery setA
  • Android 如何将总天数准确更改为年、月、日?

    我正在做一个应用程序 该应用程序与根据给定的生日日期输入获取一个人的年龄有关 为此 我从下面的代码中获取从该日期到当前日期的总天数 String strThatDay 1991 05 10 SimpleDateFormat formatte
  • Android 中的处理程序与异步调用

    目前我正在使用处理程序来调用 Web 服务方法以使其在后台运行 问题是它需要更多的时间来给出响应 在性能方面似乎更昂贵 现在我计划使用异步调用 哪一个是最好的 Android 中的处理程序和异步调用有什么区别 请帮我想出一个最好的解决方案
  • 上网本上可以进行Android开发吗? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我想使用我的上网本进行 Android 开发 但是当我尝试使用 Eclipse 运行 SDK 时 没有加载任何内容 上网本对于 Android 开发来
  • Android - 以编程方式选择菜单选项

    有没有办法以编程方式选择菜单选项 基本上 我希望视图中的按钮能够执行与按特定菜单选项相同的操作 我正在考虑尝试调用 onOptionsItemSelected MenuItem item 但我不知道要为菜单项添加什么 是的 有一种方法可以选
  • 插件“Android Bundle Support”不兼容

    大家好 自从上次更新以来 当我启动 android studio 时 我遇到了一个非常奇怪的错误 我有这个错误 插件错误 插件 Android Bundle Support 不兼容 直到构建 AI 195 SNAPSHOT 我在网上找不到任
  • 问题:为什么React Native Video不能全屏播放视频?

    我正在react native 0 57 7 中为android和ios创建一个应用程序并使用反应本机视频 https github com react native community react native video播放上传到的视频
  • 通过电子邮件发送文本文件附件

    我正在尝试附加一个文本文件以便通过电子邮件发送 但每当我打开电子邮件应用程序时 它都会说该文件不存在 请帮助 Intent i new Intent Intent ACTION SEND i setType text plain i put
  • Android:如何从网络异步获取搜索建议?

    我创建了一个可搜索的活动 现在 我想添加从网络服务获取的搜索建议 我想异步获取这些建议 根据添加自定义建议 http developer android com guide topics search adding custom sugge
  • Dagger 2 中“HasFragmentInjector”的实际用法是什么

    我之前已经实现了 dagger2 v2 2 但现在他们也添加了 dagger android 部分 所以我正在用它创建示例项目 我知道旧的方法论 Provide and Modules and 成分等注释 但从 Dagger 2 8 开始
  • Android 后台倒计时器

    我有一个 Android 应用程序 它管理一个倒计时器 类 CountDownTimer 它显示在应用程序屏幕中 以显示到达 00 00 还剩多少时间 我现在的问题是 当我按主页按钮或启动另一个应用程序时 应用程序 计时器不会在后台运行 所
  • 发布的 Android apk 出现错误“包文件未正确签名”

    我最近将我的应用程序上传到 Android 市场 但是由于错误 下载时它拒绝运行 包文件未正确签名 我首先使用 eclipse 发布了数据包 右键单击导出 创建密钥库然后发布 但它拒绝工作 然后我下载了 keytool 和 jarsigne

随机推荐

  • Ubuntu16.04忘记用户登录密码以及管理员密码,重置密码的解决方案

    1 问题现象 xff1a 由于自己想修改一下当前用户名 xff0c 结果乱改了部分配置文件导致登陆时 xff0c 原先的密码失效 2 问题原因 问题原因 xff0c 搞不懂 xff0c 只是修改了 etc shadow和 etc sudoe
  • 点赋科技:本地生活,如何开启复苏之路

    目前 xff0c 全球经历 这 场前所未有的疫情大流行 已经结束 xff0c 尽管 许多国家和地区的经济和社会都受到了影响 然而 xff0c 做好本地生活的复苏规划和推进 xff0c 将有助于在疫情之后尽快走出经济低迷期 xff0c 恢复社
  • 1130, "Host 'xxxx' is not allowed to connect to this MySQL server"

    问题描述 xff1a 1 在centos装好mysql后 xff0c 在python3程序中通过pymysql远程连接mysql xff0c 但是报 Host 39 39 not allowed connect错误 解决方法 xff1a 1
  • Pycharm配置Git教程

    1 使用场景 平时习惯在windows下开发 xff0c 但是我们又需要实时将远方仓库的代码clone到本地 xff0c 也许要将自己修改的代码push到远端服务器 xff0c 有很多方法可以实现这个需求 xff0c 但是所用的编辑软件不一
  • Ubuntu18.04安装NVIDIA驱动后,循环登录,登录界面进不去,输完密码又回到登录界面

    我安装的是Ubuntu18 04 5 xff0c 3090公版显卡 xff0c 在安装好驱动之后 xff0c 一直循环在登录界面 xff0c 输入密码之后一闪又回到登录界面 xff0c 重装了多次驱动还是不行 解决方法 xff1a 后来发现
  • 安装达梦数据库选择安装路径时提示“无写入权限”

    在使用中标麒麟的Linux系统虚拟机安装达梦数据库时 xff0c 遇到了选择安装路径时 xff0c 数据库安装程序报 无写入权限 问题 经过一番折腾后发现 xff0c 问题原因时系统的临时目录空间太小所导致的 解决方法 xff1a 1 重新
  • Docker部署MySQL单机版

    简单版 一 查看本机是否有MySQL及MySQL端口 防止端口占用 xff09 ps ef grep mysql 二 拉取MySQL镜像 docker pull mysql 5 7 三 运行MySQL镜像 docker run d p 33
  • win10无法关机解决方法

    win10无法关机怎么办 下面阐述一下处理的过程 1 左键双击控制面板 控制面板已放到桌面 xff0c 再单击电源选项 2 在打开的电源选项窗口 xff0c 左键点击 xff1a 选择电源按纽的功能 xff0c 打开系统设置 3 在系统设置
  • 小米电视访问电脑共享文件夹

    输入win 43 R打开运行窗口 输入control进入控制面板 点击 网络和internet 网络共享中心 更改高级共享设置 a 专用 网络设置如图 xff1a b 来宾或公用 网络设置如图 xff1a c 所有网络 设置如图 xff1a
  • 让Everything搜索结果更清爽

    Everything的文件搜索功能很强大 xff0c 但是默认设置下搜索出的结果过于丰富 xff0c 总是会有一些乱七八糟的后缀名文件 xff08 如下图 xff09 xff0c 或许我们并不想搜索出那些文件 这时我们需要对它设置里的排除列
  • 上机 Qt5.14.2 编程应用

    上机 Qt5 14 2 编程应用 关于QT Qt是一个1991年由Qt Company开发的跨平台C 43 43 图形用户界面应用程序开发框架 它既可以开发GUI程序 xff0c 也可用于开发非GUI程序 xff0c 比如控制台工具和服务器
  • Android Studio报错:Error:Could not find com.android.tools.build:gradle:4.1 记一次不长记性的坑

    本文地址 xff1a https blog csdn net zengsidou article details 79797417 看字面意思 xff0c 这个问题是Gradle没有对应版本 在搜索引擎没有找到方法之后 xff0c 尝试自己
  • VBox关闭dhcp

    VBox关闭dhcp C Program Files Oracle VirtualBox gt VBoxManage exe list dhcpservers NetworkName HostInterfaceNetworking Virt
  • Android 使用LottieAnimationView 做启动动画

    lt xml version 61 34 1 0 34 encoding 61 34 utf 8 34 gt lt RelativeLayout xmlns android 61 34 http schemas android com ap
  • Android OkHttp★

    1 OkHttp OkHttp是Square公司开发的一个处理网络请求的开源项目 是目前Android使用最广泛的网络框架 OkHttp的特点 支持HTTP 2并允许对同一主机的所有请求共享一个socket连接 如果非HTTP 2 则通过连
  • Android GestureDetector★★★

    1 GestureDetecor 用户触摸屏幕时会产生许多手势 xff0c 一般通过重写View类的onTouch 方法可以处理一些触摸事件 xff0c 但是这个方法太过简单 xff0c 如果需要处理一些复杂的手势 xff0c 用这个接口就
  • Android canvas

    1 Canvas Canvas指画布 xff0c 表现在屏幕上就是一块区域 xff0c 可以在上面使用各种API绘制想要的东西 canvas内部维持了一个mutable Bitmap xff0c 所以它可以使用颜色值去填充整个Bitmap
  • Android apk打包流程★

    1 apk打包 Android开发中打包apk主要有两种方式 使用Android Studio集成直接生成apk 使用ant工具在命令行方式下打包apk 不管哪种方式 打包apk的本质过程都是一样的 Android的apk包文件包括两部分
  • Android ViewPager用法

    1 适配器PagerAdapter ViewPager使用适配器类将数据和view的处理分离 xff0c ViewPager的适配器叫PagerAdapter xff0c 这是一个抽象类 xff0c 不能实例化 xff0c 所以它有两个子类
  • Android Fragment★★

    1 Fragment fragment译为 碎片 xff0c 是Android 3 0 xff08 API 11 xff09 提出的 xff0c 最开始是为了适配大屏的平板 Fragment看起来和Activity一样 xff0c 是一个用