作者 : 韩曙亮
转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/38064191
1. Fragement 概述
Fragement 与 Activity 生命周期关系 : Fragement 嵌入到 Activity 组件中才可以使用, 其生命周期与 Activity 生命周期相关.
-- stop 与 destroy 状态 : Activity 暂停 或者 销毁的时候, 其内部嵌入的所有的 Fragement 也会执行 暂停 或者 销毁 操作;
-- 活动状态 : 只有当 Activity 处于活动状态的时候, 我们才能操作 Fragement;
Fragement 特征 :
-- Fragement 与 Activity 交互 : Fragement 调用 getActivity() 获取其 所嵌入的 Activity, Activity 获取 FragementManager 的findFragementById() 或 findFragementByTag() 获取 Fragement;
-- Activity 增删 Fragement : Activity 调用 Fragement 的 add(), remove(), replace() 等方法 添加 删除 替换 Fragement;
-- Fragement 与 Activity 对应关系 : 一个 Activity 中可以嵌入多个 Fragement, 一个 Fragement 可以嵌入多个 Activity;
-- 生命周期受 Activity 影响 : Fragement 的生命周期 受 Activity 生命周期控制;
Fragement 作用 : Fragement 是为了 Android 中 平台电脑 UI 设计, 开发者不用设计 非常负责的 界面, 只需要设计好模块, 对UI 组件进行分组 和 模块化的设计和开发, 简化了 UI 组件;
Fragement 可复用性 : 同一个 app 应用, 可以在不同的 Activity 中加载同一个 Fragement;
2. Fragement 类 和 方法介绍
(1) Fragement 相关类介绍
Fragement 子类 :
-- DialogFragement : 对话框界面的 Fragement, 显示一个浮动的对话框, 这个对话框可以方便的与 Activity 进行交互, Activity 可以管理这个 Fragment;
-- ListFragement : 列表界面的 Fragement, 显示一个条目列表, 该列表可以设置一个适配器, 提供了许多管理 列表的函数;
-- PerformanceFragement : 选项设置界面的 Fragement, 该Fragment 创建 类似与 设置 应用程序时很管用;
-- WebViewFragement : WebView 界面的 Fragement;
(2) Fragement 生命周期相关方法介绍
onCreate() :
- onCreate(Bundle savedInstanceState)
-- 回调时机 : 在创建 Fragement 的时候回调;
-- 参数解析 : Bundle savedInstance, 用于保存 Fragment 参数, Fragement 也可以 重写 onSaveInstanceState(Bundle outState) 方法, 保存Fragement状态;
-- 执行的动作 : 获取 Frgement 显示的内容, 以及启动Fragment 传入的参数, 调用 getArguments() 获取键值对;
onCreateView() :
- onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
-- 回调时机 : Fragement 绘制界面组件 的时候回调, 该方法返回 View, 这个View就是 Fragement 本身;
-- 参数解析 : inflater 布局加载器, 是上下文传入, 不用自己创建; container 加载组件的父容器;
-- 执行的操作 : 使用 inflate 布局加载器 加载布局文件, 并未组件设置显示的值;
onPause() :
-- 回调时机 : Fragement 暂停的时候, 即进入后台的时候 回调;
3. Fragment 创建
Fragment 创建 :
-- 参数准备 : 创建一个 Bundle 对象, 并向其中设置参数 :
- Bundle bundle = new Bundle();
- bundle.putString("key", "value");
-- 创建 Fragment 对象 : 使用 new MyFragment() 创建对象, 并 调用 myFragment.setArguments(bundle)
方法传入参数;
- MyFragment myFragment = new MyFragment();
- myFragment.setArguments(bundle);
Fragment嵌入Activity方式 : Fragment 添加到 Activity 中才能显示, 以下是将 Fragment 嵌入 Activity 的方式;
-- 布局文件嵌入 : 在布局文件中 使用 元素, 通过定义 android:name = "com.example.MyFragment" 属性指定 Fragment 类;
-- 代码方式嵌入 : 调用 FragmentTransaction 对象的 add() 方法向 Activity 中添加 Fragment;
4. Fragment 与 Activity 通信
Fragment 获取 Activity : 调用 Fragment 对象的 getActivity()方法, 即可获取 Fragment 嵌入的 Activity 对象;
Activity 获取 Fragment :
-- Fragment 属性 : 在布局文件中, 可以为 元素指定 android:id 和 android:tag 属性;
-- 获取方法 : 调用 Activity 的 findFragmentById(int id) 或者 findFragmentByTag(String tag)方法;
Fragment 向 Activity 传递数据 : 将 Activity 当作接口子类对象, Fragment 中调用 Activity 中的接口方法;
-- Fragment 定义接口 : 在 Fragment 内部定义一个 Callback 接口;
-- Activity 实现该接口 : MyActivity extends Activity implement MyFragment.Callback;
-- Fragment 中获取该接口对象 : 在Fragment 中定义一个 Callback 全局变量, 然后在 onAttach(Activity activity) 方法中, 将activity 强转为 Callback 对象;
-- 调用接口方法 : 上面获取了 Callback 对象, 即Activity对象, 调用 Activity 中的 接口方法, 就能在 Fragment 中调用 Activity 对应的方法了;
Activity 向 Fragment 传递数据 :
-- 创建 Bundle 数据包 : 创建一个 Bundle 对象, 把要存放的键值对 放到这个对象中;
-- 设置 Bundle 对象给 Fragment : 调用 Fragment 对象的 setArguments(Bundle bundle) 方法, 将 Bundle 对象设置给 Fragment;
5. Fragment 事务管理
FragmentManager 功能 : FragmentManager 对象 可以通过 activity.getFragmentManager()获取;
-- 获取指定 Fragment : 通过 findFragmentById() 或者 findFragmentByTag() 方法获取指定 Fragment;
-- 弹出栈 : 通过调用 popBackStack(), 将 Fragment 从后台的 栈 中弹出;
-- 监听栈 : 通过调用 addOnBackStackChangeListener 注册监听器, 监听 后台栈变化;
FragmentTransaction 对象获取途径 :
-- 获取 FragmentManager 对象 : 调用 Activity 的 getFragmentManager() 获取 FragmentManager 对象;
-- 获取 FragmentTansaction 对象 : 调用 FragmentManager 对象的 beginTransaction() 方法获取 FragmentTransaction 对象;
FragmentTransaction(Fragment 事务)作用 : 对 Fragement 进行 增, 删 , 改 操作需要 FragmentTransaction 对象进行操作, 开启 这个事务, 获取 事务对象, 然后执行对 Fragment 的操作, 最后提交事务;
-- 开启事务 : 调用 Fragement 对象的 beginTransaction() 方法可以获取 FragementTransaction 对象;
-- 操作碎片 : FragmentTransaction 对象 中 包含了 add(), remove(), replace() 等方法;
-- 提交操作 : 当执行完 Fragement 的操作之后, 可以调用 FragementTransaction 对象的 commit() 方法提交修改;
addToBackStack()方法作用 : 该方法是 FragementTransaction 的方法, 在提交事务前调用该方法, 可以将 事务中执行的操作 添加到 back 栈中, 用户按下 回退键, 修改过的 Fragement 会 回退到 事务执行之前的状态;
6. Fragment 生命周期
(1) Fragment 状态
活动状态 : Fragment 处于前台, 可见, 可以获取焦点;
暂停状态 : Fragment 嵌入的Activity 也处于暂停状态, 即 Fragment 处于后台, 可见, 失去焦点;
停止状态 : Fragement 嵌入的 Activity 处于停止状态, 不可见, 失去焦点;
销毁状态 : Fragement 所在的 Activity 被销毁, 执行了 onDestroy() 方法, 此时 Fragement 被完全删除;
(2) Fragement 生命周期相关方法
红色方法 与 Activity 相对应, 蓝色方法 是 自身对应的方法, 棕色方法 单独对应;
onAttach() : 嵌入, Fragement 被嵌入到 Activity 时回调该方法, 只会调用一次;
onCreate() : 创建, Fragement 创建的时候回调该方法, 只会回调一次;
onCreateView() : 绘制, 在 Fragement 绘制的时候回调该方法, 该方法会返回 绘制的 View 组件;
onActivityCreated() : 界面创建, Fragement 所嵌入的 Activity 创建完成回调该方法;
onStart() : 启动, Fragement 启动时回调, 此时Fragement可见;
onResume() : 激活, Fragement 进入前台, 可获取焦点时激活;
onPause() : 暂停, Fragement 进入后台, 不可获取焦点时激活;
onStop() : 停止, Fragement 不可见时回调;
onDestroyView() : 销毁组件, 销毁 Fragement 绘制的 View 组件时回调;
onDestroy() : 销毁, 销毁 Fragement 回调;
onDetach() : 移除, Fragement 从 Activity 中移除的时候回调;
7. 代码示例
(1) 需求分析
纵向手机屏幕 : 两个界面, 每个界面都有一个 Fragement, 一个Fragement显示新闻列表, 一个Fragement 显示新闻内容;
横向手机屏幕 : 一个界面, 两个Fragement, Fragement 显示内容与上面相同;
(2) 新闻标题 Fragment
存放新闻标题的 Fragment : NewsTittleFragment.java
- package cn.org.octopus;
-
- import android.app.Activity;
- import android.app.ListFragment;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.ArrayAdapter;
- import android.widget.ListAdapter;
- import android.widget.ListView;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public class NewsTittleFragment extends ListFragment {
-
- private Callbacks activityCallback;
-
-
-
-
-
-
- public interface Callbacks{
- public void onNewsSelect(int id);
- }
-
-
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- System.out.println("onAttach");
-
- if ( ! ( activity instanceof Callbacks))
- System.out.println("Fragement in wrong Activity !");
-
-
- activityCallback = (Callbacks) activity;
- }
-
-
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- System.out.println("onCreate");
-
-
-
-
- ListAdapter adapter = new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_activated_1, android.R.id.text1, NewsContent.getInstance().news);
-
- setListAdapter(adapter);
- }
-
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- System.out.println("onCreateView");
- return super.onCreateView(inflater, container, savedInstanceState);
-
- }
-
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- System.out.println("onActivityCreated");
- }
-
-
- @Override
- public void onStart() {
- super.onStart();
- System.out.println("onStart");
- }
-
-
- @Override
- public void onResume() {
- super.onResume();
- System.out.println("onResume");
- }
-
-
- @Override
- public void onPause() {
- super.onPause();
- System.out.println("onPause");
- }
-
-
- @Override
- public void onStop() {
- super.onStop();
- System.out.println("onStop");
- }
-
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- System.out.println("onDestroyView");
- }
-
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- System.out.println("onDestroy");
- }
-
-
- @Override
- public void onDetach() {
- super.onDetach();
- System.out.println("onDetach");
- activityCallback = null;
- }
-
-
-
-
- @Override
- public void onListItemClick(ListView l, View v, int position, long id) {
- super.onListItemClick(l, v, position, id);
- activityCallback.onNewsSelect((int) id);
- }
-
-
-
-
-
-
- public void setChoiceMode(int choiceMode) {
- getListView().setChoiceMode(choiceMode);
- }
-
- }
(3) 新闻内容的 Fragment
存放新闻内容的 Fragment : NewsContentFragement.java;
- package cn.org.octopus;
-
- import android.app.Fragment;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.TextView;
-
- public class NewsContentFragement extends Fragment {
-
-
- public static final String TAG_NEWS_ID = "cn.org.octopus.news.tittle";
-
- private News news;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
-
- boolean isIllegal = getArguments().containsKey(TAG_NEWS_ID);
-
- if(isIllegal){
-
- int id = getArguments().getInt(TAG_NEWS_ID);
-
- news = NewsContent.getInstance().news_map.get(id);
- }
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
-
-
- View rootView = inflater.inflate(R.layout.fragment_news_content, container, false);
-
- TextView news_content_tittle = (TextView) rootView.findViewById(R.id.news_content_tittle);
-
- TextView news_content_content = (TextView) rootView.findViewById(R.id.news_content_content);
- if(null != news){
-
- news_content_tittle.setText(news.getTittle());
-
- news_content_content.setText(news.getContent());
- }
-
- return rootView;
- }
-
- }
(4) 新闻内容存储相关代码
新闻实体类 :
- package cn.org.octopus;
-
- public class News {
-
- private int id;
- private String tittle;
- private String content;
-
-
- public News(int id, String tittle, String content) {
- super();
- this.id = id;
- this.tittle = tittle;
- this.content = content;
- }
-
- public int getId() {
- return id;
- }
-
- public void setId(int id) {
- this.id = id;
- }
-
- public String getTittle() {
- return tittle;
- }
-
- public void setTittle(String tittle) {
- this.tittle = tittle;
- }
-
- public String getContent() {
- return content;
- }
-
- public void setContent(String content) {
- this.content = content;
- }
-
-
- @Override
- public String toString() {
-
-
- return tittle;
- }
-
- }
新闻数据 :
- package cn.org.octopus;
-
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
-
- public class NewsContent {
-
-
-
-
-
-
- private static NewsContent newsContent;
-
- public List news;
- public Map news_map;
-
- private NewsContent(){
- news = new ArrayList();
- news_map = new HashMap();
-
- News news1 = new News(0, "郭振玺敛财术", "7月30日,央视纪录频道CCTV-9总监刘文被带走。据相关报道,刘文被带走的原因是 “发现在纪录片对外采购上有财务问题”,另外,在一些高收视率的纪录片创作上,“涉嫌与隐性的植入广告有关的利益交换”。");
- News news2 = new News(1, "朝鲜新版5000朝元新钞无金日成头像", "韩国网刊《每日朝鲜》8月1日报道,已经开始流通的5000朝元新钞并未印金日成肖像,意味金日成肖像已从朝鲜货币上暂时消失。 旧版朝鲜5000元纸币上印有金日成头像。");
- News news3 = new News(2, "美国医生感染埃博拉", "菲律宾卫生部部长恩里克·奥尼亚说,目前菲律宾尚无埃博拉疫情。卫生部已通报地方卫生部门,一旦发现返菲海外劳工出现感染埃博拉病毒早期症状,立即对患者实行隔离治疗。卫生部还要求近期即将从海外回国的劳工如出现发烧、头痛、关节和肌肉疼痛、喉咙痛等症状,在回国前应获得所雇佣国家卫生部门的无感染证明,以避免埃博拉病毒传入菲律宾。");
-
- news.add(news1);
- news.add(news2);
- news.add(news3);
-
- news_map.put(news1.getId(), news1);
- news_map.put(news2.getId(), news2);
- news_map.put(news3.getId(), news3);
- }
-
-
-
-
-
-
- public static NewsContent getInstance() {
-
- if(newsContent != null)
- return newsContent;
- else
- return new NewsContent();
- }
-
- }
(5) 主界面 Actiity 代码
主界面代码 : MainActivity.java
- package cn.org.octopus;
-
- import android.app.Activity;
- import android.app.FragmentManager;
- import android.app.FragmentTransaction;
- import android.os.Bundle;
- import cn.org.octopus.NewsTittleFragment.Callbacks;
-
- public class MainActivity extends Activity implements Callbacks {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
-
- setContentView(R.layout.activity_main);
- }
-
-
-
-
-
- @Override
- public void onNewsSelect(int id) {
-
- Bundle arguments = new Bundle();
-
- arguments.putInt(NewsContentFragement.TAG_NEWS_ID, id);
-
- NewsContentFragement fragement = new NewsContentFragement();
-
- fragement.setArguments(arguments);
-
- FragmentManager manager = getFragmentManager();
-
- FragmentTransaction transaction = manager.beginTransaction();
-
- transaction.replace(R.id.news_content, fragement);
-
- transaction.commit();
- }
-
- }
(6) AndroidManifest.xml 配置文件
- xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="cn.org.octopus"
- android:versionCode="1"
- android:versionName="1.0" >
-
- <uses-sdk
- android:minSdkVersion="15"
- android:targetSdkVersion="19" />
-
- <application
- android:allowBackup="true"
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- android:theme="@style/AppTheme" >
-
-