Android Fragment

基本概念

Fragment是Android3.0后引入的一个新的API,他出现的初衷是为了适应大屏幕的平板电脑, 普通手机开发也会加入这个Fragment, 可以把他看成一个小型的Activity,又称Activity片段!

如果一个很大的界面,就一个布局,写起界面会很麻烦,而且如果组件多的话是管理起来也很麻烦!而使用Fragment 我们可以把屏幕划分成几块,然后进行分组,进行一个模块化的管理!从而可以更加方便的在 运行过程中动态地更新Activity的用户界面!

另外Fragment并不能单独使用,他需要嵌套在Activity 中使用,尽管他拥有自己的生命周期,但是还是会受到宿主Activity的生命周期的影响,比如Activity 被destory销毁了,他也会跟着销毁!

下图是文档中给出的一个Fragment分别对应手机与平板间不同情况的处理图:

PS: 简单的新闻浏览页面,使用两个Fragment分别显示新闻列表与新闻内容

Fragment的生命周期图

使用Fragment的一些要点

Fragment需要嵌套在Activity中使用,当然也可以嵌套到另外一个Fragment中,但这个被嵌套 的Fragment也是需要嵌套在Activity中的,间接地说,Fragment还是需要嵌套在Activity中!! 受寄主Activity的生命周期影响,当然他也有自己的生命周期!另外不建议在Fragment里面 嵌套Fragment因为嵌套在里面的Fragment生命周期不可控!!!

官方文档说创建Fragment时至少需要实现三个方法:onCreate( ),onCreateView( ),OnPause( ); 不过貌似只写一个onCreateView也是可以的

Fragment的生命周期和Activity有点类似:三种状态:
Resumed:在允许中的Fragment可见
Paused:所在Activity可见,但是得不到焦点
Stoped: ①调用addToBackStack(),Fragment被添加到Bcak栈 ②该Activity转向后台,或者该Fragment被替换/删除

ps:停止状态的fragment仍然活着(所有状态和成员信息被系统保持着),然而,它对用户 不再可见,并且如果activity被干掉,他也会被干掉.

Fragment的几个子类

ps:很多时候我们都是直接重写Fragment,inflate加载布局完成相应业务了,子类用的不多,等需要的 时候在深入研究!

  • 对话框:DialogFragment
  • 列表:ListFragment
  • 选项设置:PreferenceFragment
  • WebView界面:WebViewFragment

使用哪个包下的Fragment

相信很多朋友在使用Fragment的时候都会遇到下面这种情况:

那么我们到底是使用android.app下的Fragment还是用的android.support.v4.app包下 的Fragment呢?

其实都可以,前面说过Fragment是Android 3.0(API 11)后引入的,那么如果开发的app需要 在3.0以下的版本运行呢?比如还有一点点市场份额的2.3!于是乎,v4包就这样应运而生了, 而最低可以兼容到1.6版本!至于使用哪个包看你的需求了,现在3.0下手机市场份额其实已经不多了,随街都是4.0以上的,6.0十月份都出了,你说呢...所以这个时候,你可以直接使用app包下的Fragment 然后调用相关的方法,通常都是不会有什么问题的;如果你Fragment用了app包的, FragmentManager和FragmentTransaction都需要是app包的!要么用全部用app,要么全部用v4, 不然可是会报错的哦!当然如果你要自己的app对于低版本的手机也兼容的话,那么就可以选择用v4包!

使用v4包下Fragment要注意的地方

如果你使用了v4包下的Fragment,那么所在的那个Activity就要继承FragmentActivity哦! 案例:今天在xml文件中静态地载入fragment,然后重写了Fragment,但是在加载Activity的时候就报错了, 大概的提示就是Fragment错误还是找不到什么的,name属性改了几次还是错!最后才发现是用了 v4的包的缘故,只需让自己的Activity改成FragmentActivity即可!

之前写了下面这段代码,然后报错: 

5.1 Fragment基本概述

 有点莫名其妙啊,Fragment,FragmentManager,FragmentTransaction都是用的v4包啊, Activity也是继承FragmentActivity的啊?都改成app包就可以了,但是这不和我们用v4包的 前提冲突了么?其实也是有解决方法的哈?

只需要把getFragmentManager( )改成getSupportFragmentManager( )就可以了

创建一个Fragment

静态加载Fragment

定义Fragment的布局,就是fragment显示的内容

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

步骤一: 首先在MainActivity中绑定布局文件, 并且点击布局文件中的文字

public class MainActivitys extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//find views on onclick eventfindViewById(R.id.main_textView).setOnClickListener(v -> {// static load fragment.startActivity(new Intent(MainActivitys.this, StaticLoadFragmentActivity.class));});}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity2"><TextViewandroid:id="@+id/main_textView"android:layout_width="wrap_content"android:layout_height="100dp"android:gravity="center"android:text="static load fragment"android:layout_marginBottom="@android:dimen/thumbnail_width"android:layout_marginLeft="@android:dimen/thumbnail_height"android:layout_marginTop="@android:dimen/thumbnail_height" />
</LinearLayout>

步骤二: 再点击activety_main中的文字的时候加载StaticLoadFragmentActivity

public class StaticLoadFragmentActivity extends AppCompatActivity {@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_static_load_fragment);}
}

在对应的布局文件activity_static_load_fragment, 导入真正要加载的那个fragment

<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><fragmentandroid:id="@+id/listFragment"android:name="com.example.testapplication.ListFragments"android:layout_width="300dp"android:layout_height="200dp" /><!-还可以添加很多fragment--></LinearLayout>

步骤三: 创建需要加载的fragment

public class ListFragments extends Fragment {// 创建视图@Nullable@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fragment_test, container, false);TextView textView = view.findViewById(R.id.textView);textView.setText("Fragment test");return view;}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/cardview_dark_background"><TextViewandroid:id="@+id/textView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:textColor="#FFFFFF"android:textSize="20sp"android:text="TextView" />
</RelativeLayout>

动态加载Fragment

动态加载Fragment的好处是加载比较灵活, 可以加任何的判断加什么fragment, 在哪里添加fragment

步骤一: 在activity_main中创建container, 如下面代码中过的listContainer和detailContainer

<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity2"><TextViewandroid:id="@+id/main_textView"android:layout_width="match_parent"android:layout_height="100dp"android:gravity="center"android:text="static load fragment" /><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:orientation="horizontal"android:id="@+id/listContainer"android:layout_width="150dp"android:layout_margin="1dp"android:layout_height="match_parent"></LinearLayout><LinearLayoutandroid:orientation="horizontal"android:id="@+id/detailContainer"android:layout_width="200dp"android:layout_margin="1dp"android:layout_height="match_parent"></LinearLayout></LinearLayout>
</LinearLayout>

步骤二: 创建fragment

public class ListFragments extends Fragment {// 创建视图@Nullable@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fragment_test, container, false);return view;}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/cardview_dark_background"><TextViewandroid:id="@+id/textView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:textColor="#FFFFFF"android:textSize="20sp"android:text="TextView" />
</RelativeLayout>

步骤三: 通过FragmentManager将上面创建的fragment添加并且提交

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//find views on onclick eventfindViewById(R.id.main_textView).setOnClickListener(v -> {// static load fragment.startActivity(new Intent(MainActivity.this, StaticLoadFragmentActivity.class));});ListFragments listFragment = new ListFragments();getSupportFragmentManager().beginTransaction().add(R.id.listContainer, listFragment).commit();ListFragments detailFragment = new ListFragments();getSupportFragmentManager().beginTransaction().add(R.id.detailContainer, detailFragment).commit();// 移除fragmentgetSupportFragmentManager().beginTransaction().remove(detailFragment).commit();// 替换fragmentgetSupportFragmentManager().beginTransaction().replace(R.id.detailContainer, listFragment).commit();}
}

Fragment管理与Fragment事务

Fragment与Activity的交互

Activit传递数据给Fragment

在Activity中创建Bundle数据包,调用Fragment实例的setArguments(bundle) 从而将Bundle数据包传给Fragment,然后Fragment中调用getArguments获得 Bundle对象,然后进行解析就可以了

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//find views on onclick eventfindViewById(R.id.main_textView).setOnClickListener(v -> {// static load fragment.startActivity(new Intent(MainActivity.this, StaticLoadFragmentActivity.class));});// activity ---> fragment valueListFragments listFragment = ListFragments.newInstance("list");getSupportFragmentManager().beginTransaction().add(R.id.listContainer, listFragment).commit();ListFragments detailFragment = ListFragments.newInstance("detail");getSupportFragmentManager().beginTransaction().add(R.id.detailContainer, detailFragment).commit();}
}
public class ListFragments extends Fragment {public  static final String BUNDLE_TITLE = "bundle_title";private String mTitle = "sky";public static ListFragments newInstance(String title) {ListFragments fragments = new ListFragments();Bundle bundle = new Bundle();bundle.putString(BUNDLE_TITLE, title);fragments.setArguments(bundle);return fragments;}// 创建视图@Nullable@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fragment_test, container, false);TextView textView = view.findViewById(R.id.textView);textView.setText(mTitle);return view;}@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 在生命周期函数onCreate中获取这个参数if(getArguments() != null){mTitle = getArguments().getString(BUNDLE_TITLE);}}
}

如果传递的是一个对象, 那么可以用fragment对象调用需要传递的对象的set方法

private User mUser;public void setUser(User user) {mUser = user;
}public class User {}public static ListFragments newInstance(String title, User user){ListFragments fragments = new ListFragments();Bundle bundle = new Bundle();bundle.putString(BUNDLE_TITLE, title);fragments.setArguments(bundle);fragments.setUser(user);return fragments;
}

Fragment传递数据给Activity

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

步骤一: Fragment中定义一个回调接口并且接口回调

public class ListFragments extends Fragment {public  static final String BUNDLE_TITLE = "bundle_title";private String mTitle = "sky";public static ListFragments newInstance(String title) {ListFragments fragments = new ListFragments();Bundle bundle = new Bundle();bundle.putString(BUNDLE_TITLE, title);fragments.setArguments(bundle);return fragments;}// 创建视图@Nullable@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fragment_test, container, false);TextView textView = view.findViewById(R.id.textView);textView.setText(mTitle);// 点击textView, 调用回调方法textView.setOnClickListener(v -> {if(mOnTitleClickListener != null){mOnTitleClickListener.onClick(mTitle);}});return view;}@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 在生命周期函数onCreate中获取这个参数if(getArguments() != null){mTitle = getArguments().getString(BUNDLE_TITLE);}}// 设置接口的方法public void setOnTitleClickListener(OnTitleClickListener onTitleClickListener) {mOnTitleClickListener = onTitleClickListener;}// 定义变量private OnTitleClickListener mOnTitleClickListener;// 定义接口public interface OnTitleClickListener{void onClick(String title);}
}

步骤二:Activity中使用接口回调方法读数据

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//find views on onclick eventfindViewById(R.id.main_textView).setOnClickListener(v -> {// static load fragment.startActivity(new Intent(MainActivity.this, StaticLoadFragmentActivity.class));});// activity ---> fragment valueListFragments listFragment = ListFragments.newInstance("list");getSupportFragmentManager().beginTransaction().add(R.id.listContainer, listFragment).commit();// fragment value ---> activitylistFragment.setOnTitleClickListener(this::onClick);ListFragments detailFragment = ListFragments.newInstance("detail");getSupportFragmentManager().beginTransaction().add(R.id.detailContainer, detailFragment).commit();// fragment value ---> activitydetailFragment.setOnTitleClickListener(this::onClick);}public void onClick(String title) {setTitle(title); // 设置activity的标题}
}

总结下方法

在Fragment定义一个接口,接口中定义抽象方法,你要传什么类型的数据参数就设置为什么类型;
接着还有写一个调用接口中的抽象方法,把要传递的数据传过去
再接着就是Activity了,调用Fragment提供的那个方法,然后重写抽象方法的时候进行数据 的读取就可以了!

Fragment与Fragment之间的数据互传

找到要接受数据的fragment对象,直接调用setArguments传数据进去就可以了 通常的话是replace时,即fragment跳转的时候传数据的,那么只需要在初始化要跳转的Fragment 后调用他的setArguments方法传入数据即可!
如果是两个Fragment需要即时传数据,而非跳转的话,就需要先在Activity获得f1传过来的数据, 再传到f2了,就是以Activity为媒介~

FragmentManager fManager = getSupportFragmentManager( );
FragmentTransaction fTransaction = fManager.beginTransaction();
Fragmentthree t1 = new Fragmentthree();
Fragmenttwo t2 = new Fragmenttwo();
Bundle bundle = new Bundle();
bundle.putString("key",id);
t2.setArguments(bundle); 
fTransaction.add(R.id.fragmentRoot, t2, "~~~");  
fTransaction.addToBackStack(t1);  
fTransaction.commit(); 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/134344.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

改进YOLOv5小目标检测:构建多尺度骨干和特征增强模块,提升小目标检测

构建多尺度骨干和特征增强模块,提升小目标检测 背景代码使用配置文件如下🔥🔥🔥 提升小目标检测,创新提升 🔥🔥🔥 测试在小目标数据集进行提点 👉👉👉: 新设计的创新想法,包含详细的代码和说明,具备有效的创新组合 🐤🐤🐤 1. 本文包含两个创新改…

[.NET 6] IHostedService 的呼叫等等我的爱——等待Web应用准备就绪

📢欢迎点赞 :👍 收藏 ⭐留言 📝 如有错误敬请指正,赐人玫瑰,手留余香!📢本文作者:由webmote 原创📢作者格言:新的征程,我们面对的不是技术而是人心,人心不可测,海水不可量,唯有技术,才是深沉黑夜中的一座闪烁的灯塔 !序言 在这篇文章中,我将介绍如何等…

C语言练习题解析(2)

&#x1f493;博客主页&#xff1a;江池俊的博客⏩收录专栏&#xff1a;C语言刷题专栏&#x1f449;专栏推荐&#xff1a;✅C语言初阶之路 ✅C语言进阶之路&#x1f4bb;代码仓库&#xff1a;江池俊的代码仓库&#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐ 文…

[论文阅读]Coordinate Attention for Efficient Mobile Network Design

摘要 最近关于移动网络设计的研究已经证明了通道注意力(例如&#xff0c; the Squeeze-and-Excitation attention)对于提高模型的性能有显著的效果&#xff0c;但它们通常忽略了位置信息&#xff0c;而位置信息对于生成空间选择性注意图非常重要。在本文中&#xff0c;我们提出…

基于SpringbootShiro实现的CAS单点登录

概述 单点登录&#xff08;Single Sign On,SSO&#xff09;是一种登录管理机制&#xff0c;主要用于多系统集成&#xff0c;即在多个系统中&#xff0c;用户只需要到一个中央服务器登录一次即可访问这些系统中的任何一个&#xff0c;无须多次登录。常见的例子就是&#xff0c;…

Redis缓存

1. Redis缓存相关问题 1.1 缓存穿透 缓存穿透是指查询一个数据库一定不存在的数据。 我们以前正常的使用Redis缓存的流程大致是&#xff1a; 1、数据查询首先进行缓存查询 2、如果数据存在则直接返回缓存数据 3、如果数据不存在&#xff0c;就对数据库进行查询&#xff0…

企业级数据仓库-数仓实战

数仓实战 安装包大小 安装清单 环境搭建 一、环境搭建01&#xff08;机器准备&#xff09; 准备好三台虚拟机&#xff0c;并进行修改hostname、在hosts文件增加ip地址和主机名映射 。 1、设置每个虚拟机的hostname vi /etc/sysconfig/network 修改HOSTNAMEnode02修改hostna…

Llama2-Chinese项目:2.2-大语言模型词表扩充

因为原生LLaMA对中文的支持很弱&#xff0c;一个中文汉子往往被切分成多个token&#xff0c;因此需要对其进行中文词表扩展。思路通常是在中文语料库上训练一个中文tokenizer模型&#xff0c;然后将中文tokenizer与LLaMA原生tokenizer进行合并&#xff0c;最终得到一个扩展后的…

Docker网络学习

文章目录 Docker容器网络1.Docker为什么需要网络管理2. Docker网络简介3. 常见的网络类型4. docker 网络管理命令5.两种网络加入差异6.网络讲解docker Bridge 网络docker Host 网络docker Container 网络docker none 网络 Docker容器网络 1.Docker为什么需要网络管理 容器的网…

自动生成bug异常追踪-SRE与开发自动化协同

作者&#xff1a;观测云 数据智能部 产品方案架构师 范莹莹 简介 生产环境 bug 的定义&#xff1a;RUM 应用和 APM 应用的 error_stack 信息被捕捉后成为 bug。 以 APM 新增错误巡检为例&#xff0c;当出现新错误时&#xff0c;在观测云控制台的「事件」模块下生成新的事件报…

基于matlab实现的电力系统稳定性分析摆幅曲线代码

完整程序&#xff1a; clear; clc; t 0; tf 0; tfl 0.5; tc 0.5; % tc 0.05, 0.125, 0.5 sec for 2.5 cycles, 6.25 cycles & 25 cycles resp ts 0.05; m 2.52 / (180 * 50); i 2; dt 21.64 * pi / 180; ddt 0; time(1) 0; ang(1) 21.64; pm 0.9; pm1 2.44;…

java 字符串只保留数字、字母、中文

public static void main(String[] args) {String str "测 试 WG23-D";// 只留字母String s1 str.replaceAll("[^a-zA-Z]", "");// 只留数字String s2 str.replaceAll("[^0-9]", "");// 只留中文String s3 str.replaceA…

骨传导耳机有害处吗、骨传导耳机真的不好用吗?

骨传导耳机没有害处。 骨传导耳机是通过将声音传递到颅骨&#xff0c;再由颅骨传递到内耳&#xff0c;从而达到听声音的效果&#xff0c;与传统的耳机不同。 因此&#xff0c;骨传导耳机不会直接对人的身体健康、耳朵产生压力和损伤&#xff0c;也不会影响耳道和中耳的正常功能…

Jmeter性能实战之分布式压测

分布式执行原理 1、JMeter分布式测试时&#xff0c;选择其中一台作为调度机(master)&#xff0c;其它机器作为执行机(slave)。 2、执行时&#xff0c;master会把脚本发送到每台slave上&#xff0c;slave 拿到脚本后就开始执行&#xff0c;slave执行时不需要启动GUI&#xff0…

题目 1057: 二级C语言-分段函数

有一个函数如下&#xff0c;写一程序&#xff0c;输入x&#xff0c;输出y值。 保留两位小数 样例输入 1 样例输出 1.00 这道题的思路很简单&#xff0c;我直接用if判断输入的X对应的函数Y的区间&#xff0c;代入对应的函数&#xff0c;求出结果。记得变量用浮点型&#xff…

【毕设选题】opencv 图像识别 指纹识别 - python

文章目录 0 前言1 课题背景2 效果展示3 具体实现3.1 图像对比过滤3.2 图像二值化3.3 图像侵蚀细化3.4 图像增强3.5 特征点检测 4 OpenCV5 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往…

计算机竞赛 机器视觉的试卷批改系统 - opencv python 视觉识别

文章目录 0 简介1 项目背景2 项目目的3 系统设计3.1 目标对象3.2 系统架构3.3 软件设计方案 4 图像预处理4.1 灰度二值化4.2 形态学处理4.3 算式提取4.4 倾斜校正4.5 字符分割 5 字符识别5.1 支持向量机原理5.2 基于SVM的字符识别5.3 SVM算法实现 6 算法测试7 系统实现8 最后 0…

基于springboot+vue的问卷调查系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

Day42:网易云项目,路由进阶

网易云项目 创建、启动项目并配置路由 npm init vite npm i npm i vue-router npm i sass -D 在main.js中 import router from ./router createApp(App).use(router).mount(#app) 在index中配置路由 import {createRouter,createWebHistory} from vue-router import H…

【第200篇原创文章】解决低于1%概率出现的芯片VPSS模块跑飞的问题

在发布SDK内测的时候&#xff0c;我们发现在切换视频分辨率的时候有低概率出现VPSS模块跑飞的情况&#xff0c;概率低于1%&#xff0c;试个两三百次&#xff0c;能出1~2次。切换视频分辨率这个功能在安防产品上也确实存在需求&#xff0c;网络带宽不大好的地方分辨率可以适当下…