Android之Fragment(一)

Fragment的产生与介绍

Android运行在各种各样的设备中,有小屏幕的手机,超大屏的平板甚至电视。针对屏幕尺寸的差距,很多情况下,都是先针对手机开发一套App,然后拷贝一份,修改布局以适应平板神马超级大屏的。难道无法做到一个App可以同时适应手机和平板么,当然了,必须有啊。Fragment的出现就是为了解决这样的问题。你可以把Fragment当成Activity的一个界面的一个组成部分,甚至Activity的界面可以完全有不同的Fragment组成,更帅气的是Fragment拥有自己的生命周期和接收、处理用户的事件,这样就不必在Activity写一堆控件的事件处理的代码了。更为重要的是,你可以动态的添加、替换和移除某个Fragment。

Fragment的生命周期

Fragment必须是依存与Activity而存在的,因此Activity的生命周期会直接影响到Fragment的生命周期。官网这张图很好的说明了两者生命周期的关系:
这里写图片描述

可以看到Fragment比Activity多了几个额外的生命周期回调方法:
1. onAttach(Activity)
当Fragment与Activity发生关联时调用。
2. onCreateView(LayoutInflater, ViewGroup,Bundle)
创建该Fragment的视图
3. onActivityCreated(Bundle)
当Activity的onCreate方法返回时调用
4. onDestoryView()
与onCreateView想对应,当该Fragment的视图被移除时调用
5. onDetach()
与onAttach相对应,当Fragment与Activity关联被取消时调用

注意:除了onCreateView,其他的所有方法如果你重写了,必须调用父 类对于该方法的实现,

静态使用Fragment

这是使用Fragment最简单的一种方式,把Fragment当成普通的控件,直接写在Activity的布局文件中。步骤:
1. 继承Fragment,重写onCreateView决定Fragemnt的布局
2. 在Activity中声明此Fragment,就当和普通的View一样
下面展示一个例子(我使用2个Fragment作为Activity的布局,一个Fragment用于标题布局,一个Fragment用于内容布局):
TitleFragment的布局文件:

<?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="45dp"  android:background="@drawable/title_bar" >  <ImageButton  android:id="@+id/id_title_left_btn"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:layout_centerVertical="true"  android:layout_marginLeft="3dp"  android:background="@drawable/showleft_selector" />  <TextView  android:layout_width="fill_parent"  android:layout_height="fill_parent"  android:gravity="center"  android:text="我不是微信"  android:textColor="#fff"  android:textSize="20sp"  android:textStyle="bold" />  </RelativeLayout>  

TitleFragment

package com.zhy.zhy_fragments;  import android.app.Fragment;  
import android.os.Bundle;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.view.ViewGroup;  
import android.widget.ImageButton;  
import android.widget.Toast;  public class TitleFragment extends Fragment  
{  private ImageButton mLeftMenu;  @Override  public View onCreateView(LayoutInflater inflater, ViewGroup container,  Bundle savedInstanceState)  {  View view = inflater.inflate(R.layout.fragment_title, container, false);  mLeftMenu = (ImageButton) view.findViewById(R.id.id_title_left_btn);  mLeftMenu.setOnClickListener(new OnClickListener()  {  @Override  public void onClick(View v)  {  Toast.makeText(getActivity(),  "i am an ImageButton in TitleFragment ! ",  Toast.LENGTH_SHORT).show();  }  });  return view;  }  
}  

同理还有ContentFragment的其布局文件:

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:orientation="vertical" >  <TextView  android:layout_width="fill_parent"  android:layout_height="fill_parent"  android:gravity="center"  android:text="使用Fragment做主面板"  android:textSize="20sp"  android:textStyle="bold" />  </LinearLayout>  
ackage com.zhy.zhy_fragments;  import android.app.Fragment;  
import android.os.Bundle;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.ViewGroup;  public class ContentFragment extends Fragment  
{  @Override  public View onCreateView(LayoutInflater inflater, ViewGroup container,  Bundle savedInstanceState)  {  return inflater.inflate(R.layout.fragment_content, container, false);  }  }  

MainActivity

package com.zhy.zhy_fragments;  import android.app.Activity;  
import android.os.Bundle;  
import android.view.Window;  public class MainActivity extends Activity  
{  @Override  protected void onCreate(Bundle savedInstanceState)  {  super.onCreate(savedInstanceState);  requestWindowFeature(Window.FEATURE_NO_TITLE);  setContentView(R.layout.activity_main);  }  }  

Activity的布局文件:

<RelativeLayout 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" >  <fragment  android:id="@+id/id_fragment_title"  android:name="com.zhy.zhy_fragments.TitleFragment"  android:layout_width="fill_parent"  android:layout_height="45dp" />  <fragment  android:layout_below="@id/id_fragment_title"  android:id="@+id/id_fragment_content"  android:name="com.zhy.zhy_fragments.ContentFragment"  android:layout_width="fill_parent"  android:layout_height="fill_parent" />  </RelativeLayout>  

是不是把Fragment当成普通的View一样声明在Activity的布局文件中,然后所有控件的事件处理等代码都由各自的Fragment去处理,瞬间觉得Activity好干净有木有代码的可读性、复用性以及可维护性是不是瞬间提升了~下面看下效果图:

这里写图片描述

动态的使用Fragment

上面已经演示了,最简单的使用Fragment的方式~下面介绍如何动态的添加、更新、以及删除Fragment
为了动态使用Fragment,我们修改一下Actvity的布局文件,中间使用一个FrameLayout,下面添加四个按钮

<RelativeLayout 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" >  <fragment  android:id="@+id/id_fragment_title"  android:name="com.zhy.zhy_fragments.TitleFragment"  android:layout_width="fill_parent"  android:layout_height="45dp" />  <include  android:id="@+id/id_ly_bottombar"  android:layout_width="fill_parent"  android:layout_height="55dp"  android:layout_alignParentBottom="true"  layout="@layout/bottombar" />  <FrameLayout  android:id="@+id/id_content"  android:layout_width="fill_parent"  android:layout_height="fill_parent"  android:layout_above="@id/id_ly_bottombar"  android:layout_below="@id/id_fragment_title" />  </RelativeLayout>  

底部四个按钮的布局就不贴了,到时看效果图就明白了~~
下面主Activity

package com.zhy.zhy_fragments;  import android.app.Activity;  
import android.app.FragmentManager;  
import android.app.FragmentTransaction;  
import android.os.Bundle;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.view.Window;  
import android.widget.LinearLayout;  public class MainActivity extends Activity implements OnClickListener  
{  private LinearLayout mTabWeixin;  private LinearLayout mTabFriend;  private ContentFragment mWeixin;  private FriendFragment mFriend;  @Override  protected void onCreate(Bundle savedInstanceState)  {  super.onCreate(savedInstanceState);  requestWindowFeature(Window.FEATURE_NO_TITLE);  setContentView(R.layout.activity_main);  // 初始化控件和声明事件  mTabWeixin = (LinearLayout) findViewById(R.id.tab_bottom_weixin);  mTabFriend = (LinearLayout) findViewById(R.id.tab_bottom_friend);  mTabWeixin.setOnClickListener(this);  mTabFriend.setOnClickListener(this);  // 设置默认的Fragment  setDefaultFragment();  }  private void setDefaultFragment()  {  FragmentManager fm = getFragmentManager();  FragmentTransaction transaction = fm.beginTransaction();  mWeixin = new ContentFragment();  transaction.replace(R.id.id_content, mWeixin);  transaction.commit();  }  @Override  public void onClick(View v)  {  FragmentManager fm = getFragmentManager();  // 开启Fragment事务  FragmentTransaction transaction = fm.beginTransaction();  switch (v.getId())  {  case R.id.tab_bottom_weixin:  if (mWeixin == null)  {  mWeixin = new ContentFragment();  }  // 使用当前Fragment的布局替代id_content的控件  transaction.replace(R.id.id_content, mWeixin);  break;  case R.id.tab_bottom_friend:  if (mFriend == null)  {  mFriend = new FriendFragment();  }  transaction.replace(R.id.id_content, mFriend);  break;  }  // transaction.addToBackStack();  // 事务提交  transaction.commit();  }  }  

可以看到我们使用FragmentManager对Fragment进行了动态的加载,这里使用的是replace方法~~下一节我会详细介绍FragmentManager的常用API。

注:如果使用Android3.0以下的版本,需要引入v4的包,然后Activity继承FragmentActivity,然后通过getSupportFragmentManager获得FragmentManager。不过还是建议版Menifest文件的uses-sdk的minSdkVersion和targetSdkVersion都改为11以上,这样就不必引入v4包了。

代码中间还有两个Fragment的子类,ContentFragment上面已经见过,FriendFragment其实类似:

package com.zhy.zhy_fragments;  import android.app.Fragment;  
import android.os.Bundle;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.ViewGroup;  public class FriendFragment extends Fragment  
{  @Override  public View onCreateView(LayoutInflater inflater, ViewGroup container,  Bundle savedInstanceState)  {  return inflater.inflate(R.layout.fragment_friend, container, false);  }  }  

效果如下

这里写图片描述

Fragment家族常用的API

Fragment常用的三个类:

  1. android.app.Fragment 主要用于定义Fragment
  2. android.app.FragmentManager 主要用于在Activity中操作Fragment
  3. android.app.FragmentTransaction 保证一些列Fragment操作的原子性,熟悉事务这个词,一定能明白~

获取FragmentManage的方式:

getFragmentManager() // v4中,getSupportFragmentManager

主要的操作都是FragmentTransaction的方法

  1. FragmentTransaction transaction = fm.benginTransatcion();//开启一个事务
  2. transaction.add() //往Activity中添加一个Fragment
  3. transaction.remove() //从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈(回退栈后面会详细说),这个Fragment实例将会被销毁。
  4. transaction.replace() //使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体~
  5. transaction.hide() //隐藏当前的Fragment,仅仅是设为不可见,并不会销毁
  6. transaction.show() //显示之前隐藏的Fragment
  7. detach() //会将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护。
  8. attach() //重建view视图,附加到UI上并显示。
  9. transatcion.commit()//提交一个事务

注意:常用Fragment的哥们,可能会经常遇到这样Activity状态不一致:State loss这样的错误。

主要是因为:commit方法一定要在Activity.onSaveInstance()之前调用。
上述,基本是操作Fragment的所有的方式了,在一个事务开启到提交可以进行多个的添加、移除、替换等操作。

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

  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。

上述已经介绍完成了Fragment常用的一些方法,相信看完,大家一定清楚了Fragment的产生理由,以及如何使用Fragment,再根据API的讲解,也能明白,曾经为何觉得Fragment会出现一些列乱七八槽的问题,终究是因为没有弄清楚其生命周期。

参考链接:

Android Fragment 真正的完全解析(上) - Hongyang - 博客频道 - CSDN.NET

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

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

相关文章

《Python快速入门》基础知识扫盲课

据说:看我文章的帅帅 都有个习惯:先点赞、收藏再看 目录 🐜 1、Python 初体验 Pycharm 第一个程序 交互式编程第一个程序

数字技术对就业的影响分析

来源&#xff1a; 腾讯研究院技术是增长之源&#xff0c;就业是民生之本。技术进步对就业具有双重影响&#xff0c;它不仅带来新的工作机会&#xff0c;改善人们的生活&#xff1b;也会替代一些原有岗位&#xff0c;带来“技术性失业”。1930年&#xff0c;英国伟大的经济学家凯…

Android之Fragment(二)

本文主要内容 如何管理Fragment回退栈 Fragment如何与Activity交互 Fragment与Activity交互的最佳实践 没有视图的Fragment的用处 使用Fragment创建对话框 如何与ActionBar&#xff0c;MenuItem集成等 管理Fragment回退栈 类似与Android系统为Activity维护一个任务栈&#…

带你薅“云”羊毛:定个小目标,先薅他一年

点赞 ➕ 评论 ➕ 收藏 养成三连好习惯 一、2022年了&#xff0c;一块钱能干什么&#xff1f; 1块钱 能买一瓶矿泉水 1块钱 能坐一次公交 1块钱 竟然能买来一年的云服务器 哈哈哈&#xff0c;今天西红柿就带大家一块钱白嫖京东云服务器&#xff0c;当然&#xff0c;氪金也是…

ubuntu下搭建android开发环境(转载)

在ubuntu下搭建android开发环境&#xff0c;准备学习一下android开发。 1、安装JDK 首先到oracle的官网上下载linux版本的JDK&#xff08;网址为:http://www.oracle.com/technetwork/java/javase/downloads/jdk-6u26&#xff0d;download-400750.html&#xff09;&#x…

《瓦森纳协定》——光刻机为什么就是不卖给中国!

来源&#xff1a;金属加工&#xff08;ID&#xff1a;mw1950pub&#xff09;谈起光刻机相信大家首先想到的是荷兰&#xff0c;确实如此&#xff0c;荷兰光刻机在全球都是数一数二的&#xff0c;就连最顶尖的光刻机制造公司ASML也位于荷兰&#xff0c;二荷兰光刻机之所以这么出名…

Material Design入门(三)

本文主要包括 CollapsingToolbarLayout实现滚动动画效果 ViewPagertabLayout实现左右类Tab效果 控件介绍 这次需要用到得新控件比较多&#xff0c;主要有以下几个&#xff1a; CoordinatorLayout 组织它的子views之间协作的一个Layout&#xff0c;它可以给子View切换提供…

干货|2018物流机器人行业报告发布!不容错过

来源&#xff1a;楼今岁阅 摘要&#xff1a;2018年&#xff0c;我们都在谈智能家居、智能交通、智能工业、智能安防等热门物联网话题&#xff0c;并且预计到2020年&#xff0c;中国物联网的整体规模将超过1.8万亿元。发展如此迅速&#xff0c;其涉及的领域一定会越来越广&#…

【年度回忆录】如何做到1年90000粉丝?

亲爱的小伙伴&#xff1a; 小伙伴你好&#xff0c;我是不吃西红柿&#xff0c;仅以此文作为 2021 年终总结&#xff0c;顺便跟大家分享一些博主的心得经验&#xff0c;希望你我和 CSDN 都越来越好&#xff01; 一、C站点滴 翻开 2021 CSDN 年度回忆录&#xff0c;有种难以言…

Material Design综合实例

背景知识 drawlayout的使用 recycleView的使用 CardView的使用 一些开源动画库的使用 ImageView的scaleType属性与adjustViewBounds属性 &#xff0c;参考链接&#xff1a; ImageView的android:adjustViewBounds属性 - - ITeye技术网站 Android ImageView的scaleType属性与…

DARPA将开发无需手术的神经技术,实现脑机接口

来源&#xff1a;IEEE电气电子工程师学会到目前为止&#xff0c;DARPA&#xff08;美国国防部高级研究计划局&#xff09;的神经科学项目部&#xff08;也称为国防部疯狂科学部门&#xff09;一直专注于可服务于那些因身体或大脑残疾回国的士兵的技术&#xff0c;例如&#xff…

2018年全球自动驾驶法律政策研究 | 附报告下载

来源&#xff1a;腾讯研究院摘要&#xff1a;2018年9月13日&#xff0c;在中国法学会研究部、腾讯研究院联合举办的“‘法律人的互联网思维’系列研修会第二期——自动驾驶汽车的技术、产业和法律维度”上&#xff0c;腾讯研究院发布《2018年全球自动驾驶法律政策研究报告》。0…

全球最具影响力AI机构TOP100排名:中国5所高校1所研究院入围

来源&#xff1a;学术头条&#xff08;SciTouTiao&#xff09;现在“人工智能”&#xff08;ArtificialIntelligence&#xff09;一词时常“做客”各大媒体平台&#xff0c;成为人们所关注的热点话题&#xff0c;而在学术圈&#xff0c;AI技术同样也是最具活力与吸引力的研究课…

安卓开源库之动画篇

本文主要介绍收集了笔者所用过的开源动画库&#xff0c;达到一些比较好看的效果。 一个富有动感的 Sheet 链接&#xff1a; zzz40500/AndroidSweetSheet: 一个富有动感的Sheet(选择器) 效果如下 示例代码 package com.zj.testsheet;import android.os.Bundle; import andr…

《Python 黑科技》代理ip奇技淫巧

点赞 ➕ 评论 ➕ 收藏 三连再看你最帅 目录 &#x1f41b; 1、什么是住宅动态ip&#xff1f; &#x1f98b; 1.1 动态ip优点是什么&#xff1f; &#x1f40c; 1.2 环境准备 &#x1f41e; 1.3 获取代理ip &#x1f41c; 2、使用代理IP &#x1f424; 2.1 浏览器使用代理…

MIT发布2018年全球10大突破性技术!

来源&#xff1a; 数字化企业作为全球最为著名的技术榜单之一&#xff0c;《麻省理工科技评论》全球十大突破性技术具备极大的全球影响力和权威性&#xff0c;至今已经举办了18年。每年上榜的技术突破&#xff0c;有的已经在现实中得以应用&#xff0c;有的还尚需时日&#xff…

Android实现监测网络状态

本文主要用到了安卓监测网络状态变化功能&#xff0c;实现了WIFI,3G,无网络状态切换时发出通知的功能。 主要知识点 servicebroadcast接口回调实现 service的基本知识 service可分为 按运行地点分类 本地服务 远程服务 按按运行类型分类&#xff1a; 前台服务后台服务按…

jni 步骤

这是我转的文章&#xff0c;是篇外文翻译&#xff0c;将介绍如何学习安装 Android NDK 并开始使用它。在这一教程结束后&#xff0c;将创建你自己的项目&#xff0c;从 Java 代码简单地调用原生C 语言代码。教程细节技术&#xff1a;Android SDK、NDK、C 语言难度&#xff1a;进…

德勤:2025年汽车行业价值链的四个合理情境

来源&#xff1a;亿欧摘要&#xff1a;近日&#xff0c;德勤发布《未来汽车行业价值链&#xff1a;2025年以后》&#xff0c;假设在大部分整车企业都有变革意愿的情境下&#xff0c;识别出四个2025年整车企业价值链可能具有的合理设定。随着自动驾驶、共享经济等新技术以及新商…

盘点英特尔、苹果、高通、AMD 处理器重大 Bug,硬件的坑软件能填?

来源&#xff1a;21ic电子网英特尔的CPU存在两大漏洞 ——Meltdown 和 Spectre&#xff0c;波及自 1995 年以来所有使用英特尔芯片的硬件设备。不止 Linux、Android、Windows、苹果 OS X 等操作系统&#xff0c;AWS、Azure、谷歌云等云计算提供商均受到影响&#xff0c;其威胁范…