# **Fragment**
* * * * *
1. Fragment是什么
2. Fragment能实现哪些效果?为什么我要使用Fragment
3. Fragment的具体使用细节?
4. 如何向别人讲解,熟练使用Fragment?
## **一.Fragment是什么?**
Fragment是Android系统提供的“组件”[1],以提供“灵活构建UI布局”能力。
> 注:什么是组件?组件,是由系统/依赖库等其他外部因素创建的“Java类”,它们存在的形式,通常是Java类;不同组件唯一的不同之处是——不同的组件,提供各不相同的“能力”。
>
## **二.Fragment经常出现在哪些经典的UI布局当中?**
* 左右布局,如新闻模块、侧边栏导航模块、外卖点餐系统
* 点击列表查看详情布局,如新闻列表-查看新闻详情
* 常见tab切换页
* 此次研究对象,漫画APP中,使用到Fragment的模块和页面:
1. 主页
2. 点击侧边栏显示详情内容
## **三.如何开始使用Fragment?**
为了保证资料来源的权威性,本人将直接引用Google官方提供的Android开发资料
在使用Fragment之前,再次明确我作此小节的目的:
学会创建、实现、定义、引用Fragment。——是本小节的核心、也是我作此文的目的
注意,在确保诸位能学会Fragment之前,一定要牢记这里包含了四步曲:
前两步定义、创建、实现只是作好了”食材“;
第三、四步正确定义、引用Fragment,才能真正的发挥Fragment功力,进而用Fragment作出”美味可口的大餐“。
我都有点迫不及待了,快来和我一起了解Fragment使用方法吧!
### **创建和实现Fragment**
创建Fragment的方式一共有两步:代码创建Java类和XML创建视图布局。
创建Java文件的步骤如下:
在你的src/main/java 目录下,创建一个名为ArticleFragment的文件,粘贴复制下面的代码
~~~
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.ViewGroup;
public class ArticleFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.article_view, container, false);
}
}
~~~
瞧,动态创建的方式如此简单,就跟我们初学Java时,创建一个Person类那样简单,不同的是,我们需要通过import导入Android的开发包;当然,按住ctrl+shift+o,即可快速导入Fragment关联的包;还有关键的一点,在实际开发中,上述代码将会被重复写无数多次,你有的是机会去记住这段代码。而此刻,我们学习的重点是——哪一段代码,可以创建Fragment,因此,作为新手,我建议直接粘贴复制此段代码。以便于进行下一步练习。
我们再来看看创建Fragment视图布局的方式,也就是说,我们即将实现Fragment的能力——UI布局:
在你的res/layout/目录下创建news_articles.xml文件,直接粘贴复制下面的布局语法
<FrameLayout 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"
>
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
瞧,依然是如此的简单!我们在xml文件中,加入了TextView文本组件,这即将是Fragment要显示的内容
我们通过在Java目录下创建Java文件,在laout目录下创建xml文件的形式,完成了第一步:Fragment的创建。可是,完成创建和实现,并不意味着就万事大吉了,我们还需要实现它、正确定义、引用它,才能在手机屏幕上看到Fragment这个可爱的家伙!
### **定义Fragment**
老实说,定义Fragment并不简单,动态定义和静态定义
动态定义,在Java文件中通过new ArticleFragment()的方式,直接完成对Fragment的定义,这样引用,也是动态引用的
静态定义,是在诸如res/laout/activity_home.xml中(知识举例),创建Fragment,通过引用activity.xml中的fragment,完成静态定义、这样定义,引用方式也称之为静态引用
先说静态引用,这是我们上一步创建的
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<fragment android:name="com.example.android.fragments.ArticleFragment"
android:id="@+id/article_fragment"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
引用Fragment
下列这段代码,讲解了在activity中静态引用fragment,这样activity讲直接显示news_articles.xml里的布局,连fragment得实例化对象都还没看到!
~~~
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.news_articles);
}
}
~~~
这种静态引用的核心,就是通过系统已经定义好的函数——setContentView()直接加载指定的xml布局文件
记住,setCOntentView()函数,这个函数相当关键。
接着讲动态引用,动态引用Fragment,正是本文核心中的核心。实际开发,也是用的最多的!
先在res/layout/目录下创建news_article.xml文件,语法如下
~~~
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
~~~
上述语法只是创建了一个framelayout布局(不是fragment布局),没有任何内容
(在看下面这段代码之前,先使用第一步创建ArticleFragment的方式,再创建一个类似的名为HeadlineFragment的Fragment)
~~~
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.news_articles);
// Check that the activity is using the layout version with
// the fragment_container FrameLayout
if (findViewById(R.id.fragment_container) != null) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (savedInstanceState != null) {
return;
}
// Create a new Fragment to be placed in the activity layout
HeadlinesFragment firstFragment = new HeadlinesFragment();
// In case this activity was started with special instructions from an
// Intent, pass the Intent's extras to the fragment as arguments
firstFragment.setArguments(getIntent().getExtras());
// Add the fragment to the 'fragment_container' FrameLayout
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, firstFragment).commit();
}
}
}
~~~
上述代码有三处关键的地方
1. setContentView(R.layout.news_articles);
2. HeadlinesFragment firstFragment = new HeadlinesFragment();
3. getSupportFragmentManager().beginTransaction() .add(R.id.fragment_container, firstFragment).commit();
解释和说明:
1. 先为Activity加载布局,Activity此刻只有一个framelayout空布局
2. 再动态创建一个Fragment子类对象——HeadlinesFragment
3. 最最关键的,第三段超长的代码链,一句话、一个标点符号都不能错。
**最为关键**的是.add(R.id.fragment_container, firstFragment)
R.id.fragment_container指的是activity首先加载的framelayout空布局id,
而firstFragment指的是fragment对象,通过add()函数,firstFragment讲被添加到activity中,从而显示到屏幕上!
当然,千万别忘了commit()!只有确保commit,才能保证系统正确的执行你前面写的一大段代码!
## **四.Fragment的使用细节**
老实说,Fragment的使用细节,没什么值得讲的地方,新手如果确保前三小节看懂、会用,避免语法错误、步骤错误,使用Fragment就不可能出现BUG。
但有几点,值得我分享给诸位,坐下来好好谈谈的技术点:
1. 先再次复述一遍Fragment的创建、实现、定义、引用的步骤,尤其是动态引用小节中的第三步,那段超长的代码链,是否倒背如流?
2. Acitivity、Fragment、FragmentManager、FragmentTransaction,
2.1Activity与Fragment的关系——生命周期是如何影响Activity和Fragment的
2.1FragmentTransaction的API,除了add(),试试其他方法replace()、hide()、remove()等
细节部分,互联网上有太多的Android同仁介绍过了,写多了,对于本人,不能给予Android领域更多贡献,在这里便不多费口舌,献出我认为较好的关于“Fragment使用细节”的链接,有兴趣的可以深究。
1.Android API网站——FragmentTransaction索引
https://developer.android.google.cn/reference/android/app/FragmentTransaction.html
2.Android Fragment培训课程
https://developer.android.google.cn/training/basics/fragments/index.html
2.Android Fragment 真正的完全解析(下)
http://blog.csdn.net/lmj623565791/article/details/37970961/
## **五.学会向别人讲解Fragment**
当你有向别人讲解Fragment的需要时,你一定身处下面两种角色之一:毕业答辩、求职招聘。
* 参与毕业答辩的同学,担心被老师问到Fragment,手慌脚乱,不知从何说起
* 即将参加求职招聘的同仁,不善言辞的程序员,紧张起来,也容易乱说一通。
此节的目的,正在于此。
#### 1.Fragment是什么
答:谷歌提供的碎片化组件,可以附着在Activity上,组成多个碎片布局。
#### 2.Fragment如何用,
3.FragmentManager 、FragmentTransition是Fragment的管理器和发布器,管理器既可以将Fragment绑定至Activity上,也可以创建发布器对象。一旦创建好了发布器对象,发布器FragmentTransition便可通过commit()函数,通知Actiivty,将Fragment添加到屏幕之上。
#### 3.Fragment如何管理?
这里的管理,往小了说,是通过管理器FragmentManager管理的,FragmentManager有强大、全面的管理Fragment的函数,对Fragment的操作,包括索引、查找、增加、删除、压栈、出栈、回退等功能。时间以及瞬时记忆力等原因,不在这里一一说明了。
但有一点,是面试、答辩值得一说的,就是Fragment管理器,能实现哪些常见的需求?
比如查找,可以找到已经创建且并未销毁的Fragment,这样可以复用对象,减少内存消耗;
比如增加,可以继续创建一个Fragment,附着在Activity上,旧的Fragment,只是看不见、或者暂时存放至后台了
比回退,可以实现浏览器打开一系列页面,按住Back键位,还能从当前页面,返回到上一历史页面去,这在实际开发,是相当有用的。
但具体的API,面试、答辩,并不一定需要说出来,最重要的是,讲出来,Fragment以及Fragment的管理器、发布器,可以实现哪些功能和需求,实际开发,是允许我们去查询资料和文档的!