当前位置: 首页 > news >正文

activity 点击后传递数据给fragment_51、android中fragment的使用

什么是Fragment?

    简单来说,Fragment其实可以理解为一个具有自己生命周期的控件,只不过这个控件又有点特殊,它有自己的处理输入事件的能力,有自己的生命周期,又必须依赖于Activity,能互相通信和托管 。

  说白了:Fragment也是用来显示的;就是可以把“按钮(Button)”、“文本(TextView)”等组件放在上面,再通过“onCreateView”方法返回的“view”,在“Activity”中显示出来。但是,Fragment的显示依赖于“Activity”,需要通过“Activity”将其展示出来,它本身不具有显示的功能。

     Fragment,也简称为:碎片,是Android 3.0(API 11)提出的,为了兼容低版本,support-v4库中也开发了一套Fragment API,最低兼容Android 1.6。

    过去support-v4库是一个jar包,24.2.0版本开始,将support-v4库模块化为多个jar包,包含:support-fragment, support-ui, support-media-compat等,这么做是为了减少APK包大小,你需要用哪个模块就引入哪个模块。

    因为support库是不断更新的,因此建议使用support库中的android.support.v4.app.Fragment,而不要用系统自带的android.app.Fragment。而如果要使用support库的Fragment,Activity必须要继承FragmentActivity(AppCompatActivity是FragmentActivity的子类)。

基本使用

(1)将Fragment当作控件使用

这种方法是使用Fragment的最简单的一种方式了,我们只需要声明一个类继承自Fragment实现其onCreateView方法,并将fragment声明在Activity的xml里即可。我们来看代码:


AFragment.java:

@Nullable@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,    Bundle savedInstanceState) {  return inflater.inflate(R.layout.afragment, container, false);}

afragment.xml:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent">    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerInParent="true"        android:text="AFragment" />RelativeLayout>

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns: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="com.xn.myproject.MainActivity">    <fragment        android:id="@+id/fragmenta"        android:name="com.xn.myproject.fragment.AFragment"        android:layout_width="match_parent"        android:layout_height="match_parent" />LinearLayout>

效果图:

eb39734c1b16ab641ac627be15819d1f.png

这样我们就将AFragment作为一个控件显示出来了,十分简单,只是需要注意fragment控件一定要加id属性即可,否则会崩溃。。但是将Fragment作为一个控件来使用就不推荐了。我们下面看看其它的使用方法:

(2)FragmentManager动态加载Fragment

在代码中通过FragmentManager获取FragmentTransaction来进行Fragment的动态添加才是我们最常用的使用方式。先来看代码:
MainActivity:

    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mAFragment = new AFragment();        getFragmentManager().beginTransaction()                .replace(R.id.main_container, mAFragment).commit();        getFragmentManager().beginTransaction().show(mAFragment);    }

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns: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="com.xn.myproject.MainActivity">    <FrameLayout        android:id="@+id/main_container"        android:layout_width="match_parent"        android:layout_height="match_parent" />LinearLayout>

这里我们在Activity中获取FragmentManager然后再进一步获取到FragmentTransaction对象将我们new出来的AFragment add到FrameLayout中。


这种动态加载Fragment的方式十分灵活,可以让我们在代码当中动态的决定加载哪些Fragment显示出来。这里我们需要重点关注的是FragmentTransaction对象。除了例子当中使用的add操作以外,它还有replace,hide,show,remove等操作。

1)add(int containerViewId, Fragment fragment)

这个方法是将fragmen添加到我们指定id的layout中.

2)hide(Fragment fragment)和show(Fragment fragment)

隐藏或者显示指定的fragment,类似于我们在View中经常使用的setVisibly方法,需要注意的是,这里的hide和show仅仅只是让fragment显示和隐藏,不会对fragment进行销毁,甚至我们在hide的时候fragment的onPause方法都没有被调用。

3)remove(Fragment fragment)

会将fragment移除,如果被移除的Fragment没有添加到回退栈,该Fragment会同时被销毁。

4)replace(int containerViewId, Fragment fragment)

replace方法是用来进行替换的,实际上也就是对指定的layout id先remove掉其fragment,然后再add上去我们指定的fragment的一种组合操作。

5)detach()

会将view从UI中移除,和remove()不同,此时fragment并没有与Activity断绝关系,所以生命周期的onDestroy方法和onDetach方法并没有被调用

6)attach()

重建view视图,附加到UI上并显示,如果调用完detach方法后再来调用该方法的话不会去走onAttach和onCreate方法。

需要注意的是,我们在进行了上述的各种操作以后一定要调用commit方法提交事务才能生效。

Fragment生命周期

5b6c679d9204abba66ab5e34e65f5f0b.png

上图所示我们可以看到Fragment生命周期对应Activity的各个生命周期方法。

部分方法说明:

1).onAttach

当该Fragment与Activity发生关联的时候调用,注意的是这个方法里会给我们传入一个Context上下文参数,此时我们可以将其存入成员变量中进行使用,避免在代码中调用getActivity()出现的空指针异常。

2).onCreate

当创建Fragment的时候调用与onAttach方法是一起调用的,如果没有调用到onAttach方法就不会调用该方法。

3).onCreateView

每次创建、绘制Fragment的View时调用,并且返回一个view对象。

4).onActivityCreated

当Fragment所在的Activity被onCreate完成时调用。

5)onDestoryView()

与onCreateView想对应,当该Fragment的视图被移除时调用。

6)onDestroy()方法

与onCreate想对应当Fragment的状态被销毁的时候进行调用。

6)onDetach()

与onAttach相对应,当Fragment与Activity关联被取消时调用,需要注意的是我们调用detach方法的时候并不会调用到该生命周期方法。

Fragment的典型应用场景

Fragment的应用场景最多的便是ViewPager+Fragment的实现,现在主流的APP几乎都能看到它们的身影,那么这一部分我就主要针对该应用场景进行分析。
ViewPager+Fragment结构
相信绝大多数的人都用ViewPager+Fragment的形式实现过界面,同时目前市面上主流的APP也都是采用这种结构来进行UI架构的,所以我们有必要单独对这种情况拿出来做一下分析。
首先我们来看一段代码:

public class MainActivity extends FragmentActivity        implements            View.OnClickListener {    private ViewPager mViewPager;    private List mList;    private Fragment mOne;    private Fragment mTwo;    private Fragment mThree;    private Fragment mFour;    private Button mOneButton;    private Button mTwoButton;    private Button mThreeButton;    private Button mFourButton;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mViewPager = (ViewPager) findViewById(R.id.content_pager);        //加载Fragment        mList = new ArrayList<>();        mOne = new OneFragment();        mTwo = new TwoFragment();        mThree = new ThreeFragment();        mFour = new FourFragment();        mList.add(mOne);        mList.add(mTwo);        mList.add(mThree);        mList.add(mFour);        mOneButton = (Button) findViewById(R.id.one);        mTwoButton = (Button) findViewById(R.id.two);        mThreeButton = (Button) findViewById(R.id.three);        mFourButton = (Button) findViewById(R.id.four);        mOneButton.setOnClickListener(this);        mTwoButton.setOnClickListener(this);        mThreeButton.setOnClickListener(this);        mFourButton.setOnClickListener(this);        //设置到ViewPager中        mViewPager.setAdapter(new ContentsPagerAdapter(                getSupportFragmentManager()));    }    @Override    public void onClick(View v) {        switch (v.getId()) {            case R.id.one :                mViewPager.setCurrentItem(0);                break;            case R.id.two :                mViewPager.setCurrentItem(1);                break;            case R.id.three :                mViewPager.setCurrentItem(2);                break;            case R.id.four :                mViewPager.setCurrentItem(3);                break;        }    }        class ContentsPagerAdapter extends FragmentStatePagerAdapter {        public ContentsPagerAdapter(FragmentManager fm) {            super(fm);        }        @Override        public Fragment getItem(int position) {            return mList.get(position);        }        @Override        public int getCount() {            return mList.size();        }    }}

在这里我们加载了4个Fragment到ViewPager中,同时我在这里使用的是
FragmentStatePagerAdapter。这里需要提到的是FragmentStatePagerAdapter与FragmentPagerAdapter的区别。FragmentPagerAdapter:对于不再需要的fragment,仅仅只会调用到onDestroyView方法,也就是仅仅销毁视图而并没有完全销毁Fragment。FragmentStatePagerAdapter:会销毁不再需要的fragment,一直调用到onDetach方法失去与Activity的绑定。销毁时,会调用onSaveInstanceState(Bundle outState)方法通过bundle将信息保存下来,当用户切换回来,可以通过该bundle恢复生成新的fragment,也就是说,我们可以在onSaveInstanceState(Bundle outState)方法中保存一些数据,在onCreate中进行恢复创建。下面我们来看一下日志就清楚了:
首先在使用FragmentPagerAdapter中的时候我们观察日志:

29aa8e457a4487dc0ef727af7f7571ba.png

首先进入的时候ViewPager处于第一个Fragment上,此时由于ViewPager的预加载功能TwoFragment也被加载了,通过日志我们就能看到。当我们此时切换到了第四个Fragment中去的时候,我们就会发现OneFragment仅仅只是调用了onDestroyView方法而已,后面的onDestroy方法很onDetach方法都没被调用到。

7e4590cdfa7c07e8beae37b278a2aca9.png

同样的操作再在FragmentStatePagerAdapter里来一遍,我们会发现当我们切换的时候One和Two的Fragment的onDestroyView,onDestroy,onDetach全部都调用到了。同时我在OnewFragment通过onSaveInstanceState方法存起来的值在下一次的onCreate的时候也能读取到。

通过上面的代码和例子我们基本搞清楚了ViewPager与Fragment如何结合起来使用,以及他们的生命周期调用我们也弄清楚了。那么我们到底什么时候用FragmentStatePagerAdapter,什么时候用FragmentPagerAdapter呢?根据我的经验来看,当页面较少的情况下可以考虑使用FragmentPagerAdapter,通过空间来换取时间上的效率。但当页面多了的时候我们就更需要使用FragmentStatePagerAdapter来做了,因为没有哪个用户希望某个应用会占爆它内存。

以上就是fragment的基本用法,如果有需要可以去官方文档详细了解:

https://developer.android.com/guide/topics/providers/content-provider-basics?hl=zh-cn

相关文章:

  • python游戏脚本dnf_一款Python自制的斗地主小游戏
  • 为什么不能用服务器名字直接远程链接_学生机简单开一个CSGO的社区服务器
  • bpmn流程图_业务架构如何创建BPMN图?
  • mysql 单表字段多少合适_公司DBA关于MySQL开发的一点经验
  • python性能测试脚本_精通Python自动化脚本-第二章 Python脚本调试和性能测试
  • python rindex_Python index和rindex方法
  • lcd图片转二进制工具_用完即走丨无需安装!900+工具在线使用,真正的NICE TOOL!...
  • fastjson jsonobject 转bean失败_漫谈FastJSON
  • vs 堆栈保留大小_亚冠杯:上海申花vs东京FC【绝密情报】
  • python文件名可以用中文吗_在文件名中可以使用“/”吗?
  • idea打开项目xml的路径飘红_从零开始搭建SpringBoot项目(小白版,踏遍万水千坑)...
  • docker 安装nginx_docker安装nginx镜像
  • 概率神经网络_深度学习算法(第33期)强化学习之神经网络策略学习平衡车
  • vasp 安装_安装Atomic Simulation Environment (ASE)
  • fastreport调用frf文件直接打印_不是我吹,20M的压缩文件我只用了1秒!
  • [译]Python中的类属性与实例属性的区别
  • 【跃迁之路】【699天】程序员高效学习方法论探索系列(实验阶段456-2019.1.19)...
  • 345-反转字符串中的元音字母
  • Android交互
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • C++类的相互关联
  • JavaScript 奇技淫巧
  • JS变量作用域
  • k8s如何管理Pod
  • PAT A1050
  • uva 10370 Above Average
  • 大快搜索数据爬虫技术实例安装教学篇
  • 二维平面内的碰撞检测【一】
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 区块链技术特点之去中心化特性
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • 我是如何设计 Upload 上传组件的
  • 字符串匹配基础上
  • const的用法,特别是用在函数前面与后面的区别
  • ​DB-Engines 11月数据库排名:PostgreSQL坐稳同期涨幅榜冠军宝座
  • ​油烟净化器电源安全,保障健康餐饮生活
  • (二十一)devops持续集成开发——使用jenkins的Docker Pipeline插件完成docker项目的pipeline流水线发布
  • (九)c52学习之旅-定时器
  • (已解决)什么是vue导航守卫
  • (转)【Hibernate总结系列】使用举例
  • (转)总结使用Unity 3D优化游戏运行性能的经验
  • .mysql secret在哪_MYSQL基本操作(上)
  • .NET 分布式技术比较
  • .NetCore 如何动态路由
  • .NET的微型Web框架 Nancy
  • .NET关于 跳过SSL中遇到的问题
  • .Net通用分页类(存储过程分页版,可以选择页码的显示样式,且有中英选择)
  • .Net转前端开发-启航篇,如何定制博客园主题
  • /usr/local/nginx/logs/nginx.pid failed (2: No such file or directory)
  • []sim300 GPRS数据收发程序
  • [1] 平面(Plane)图形的生成算法
  • [AIGC] 如何建立和优化你的工作流?
  • [BUUCTF]-PWN:[极客大挑战 2019]Not Bad解析
  • [codeforces]Recover the String
  • [Design Pattern] 工厂方法模式