• fragment详解


    作者 : 韩曙亮

    转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/38064191

    本博客代码地址 :

    -- 单一 Fragment 示例 : https://github.com/han1202012/Octopus-Fragement.git

    -- 可复用的 Fragment 示例 : https://github.com/han1202012/Octopus-Fragement_TwoModel.git

    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() :

    [java] view plain copy

    在CODE上查看代码片派生到我的代码片

    1. onCreate(Bundle savedInstanceState) 

    -- 回调时机 : 在创建 Fragement 的时候回调;

    -- 参数解析 : Bundle savedInstance, 用于保存 Fragment 参数, Fragement 也可以 重写 onSaveInstanceState(Bundle outState) 方法, 保存Fragement状态;

    -- 执行的动作 : 获取 Frgement 显示的内容, 以及启动Fragment 传入的参数, 调用 getArguments() 获取键值对;

    onCreateView() :

    [java] view plain copy

    在CODE上查看代码片派生到我的代码片

    1. onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState); 

    -- 回调时机 : Fragement 绘制界面组件 的时候回调, 该方法返回 View, 这个View就是 Fragement 本身;

    -- 参数解析 : inflater 布局加载器, 是上下文传入, 不用自己创建; container 加载组件的父容器;

    -- 执行的操作 : 使用 inflate 布局加载器 加载布局文件, 并未组件设置显示的值;

    onPause() :

    -- 回调时机 : Fragement 暂停的时候, 即进入后台的时候 回调;

    3. Fragment 创建

    Fragment 创建 :

    -- 参数准备 : 创建一个 Bundle 对象, 并向其中设置参数 : 派生到我的代码片

    1. Bundle bundle = new Bundle();  
    2. bundle.putString("key", "value"); 

    -- 创建 Fragment 对象 : 使用 new MyFragment() 创建对象, 并 调用 myFragment.setArguments(bundle) 方法传入参数;

    1. MyFragment myFragment = new MyFragment(); 
    2. myFragment.setArguments(bundle); 

    Fragment嵌入Activity方式 : Fragment 添加到 Activity 中才能显示, 以下是将 Fragment 嵌入 Activity 的方式;

    -- 布局文件嵌入 : 在布局文件中 使用 <Fragment /> 元素, 通过定义 android:name = "com.example.MyFragment" 属性指定 Fragment 类;

    -- 代码方式嵌入 : 调用 FragmentTransaction 对象的 add() 方法向 Activity 中添加 Fragment;

    4. Fragment 与 Activity 通信

    Fragment 获取 Activity : 调用 Fragment 对象的 getActivity()方法, 即可获取 Fragment 嵌入的 Activity 对象;

    Activity 获取 Fragment :

    -- 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)MainActivity.java

    一共有两个Fragment,其中有一个是在布局文件中直接定义,另外一个通过在代码中创建Fragment,然后向其中传递参数,在fragment中获取MainActivity传递过来的参数

    package com.henry.usingfragment;

    import android.app.FragmentManager;
    import android.app.FragmentTransaction;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;

    public class MainActivity extends AppCompatActivity implements NewsTitleFragment.Callbacks{
    private final String TAG="MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    }

    @Override
    public void onItemSelect(int itemId) {

    Log.i(TAG,"onItemSelect"+"id"+itemId);

    //MainActivity向Fragment传递参数,该参数在NewsContentFragment通过getArguments()获取
    Bundle arguments=new Bundle();
    arguments.putInt(NewsContentFragment.TAG_NEWS_ID,itemId);

    NewsContentFragment fragment=new NewsContentFragment();
    fragment.setArguments(arguments);

    FragmentManager fragmentManager=getFragmentManager();
    FragmentTransaction transaction=fragmentManager.beginTransaction();
    transaction.replace(R.id.news_content_fargment_container,fragment);
    transaction.commit();
    }
    }

    (2)NewsTitleFragment .java

    package com.henry.usingfragment;

    import android.app.Activity;
    import android.app.Fragment;
    import android.app.ListFragment;
    import android.content.Context;
    import android.os.Bundle;
    import android.support.annotation.Nullable;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.Adapter;
    import android.widget.ArrayAdapter;
    import android.widget.ListAdapter;
    import android.widget.ListView;

    /**
    * Created by shiyanshi on 2016/3/15.
    */
    public class NewsTitleFragment extends ListFragment {

    private final String LOG_TAG="NewsTitleFragment";

    //用于Fragment向MainActivity传递数据
    public Callbacks activityCallbacks;
    public interface Callbacks{
    public void onItemSelect(int itemId);
    }


    //用于Fragment向MainActivity传递数据
    @Override
    public void onAttach(Activity activity) {
    super.onAttach(activity);

    Log.i(LOG_TAG,"Activity:onAttach");
    if (!(activity instanceof Callbacks)){
    Log.i(LOG_TAG, "fragment in wrong activity");
    }
            //能够进行强制类型转化是因为MainActivity继承自Callbacks
    activityCallbacks=(Callbacks)activity;
    }

    @Override
    public void onAttach(Context context) {
    super.onAttach(context);
    Log.i(LOG_TAG, "Context:onAttach");
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.i(LOG_TAG, "onCreate");

    ListAdapter adapter=new ArrayAdapter<News>(getActivity(),
    android.R.layout.simple_list_item_1,
    android.R.id.text1,
    NewsContent.getInstance().news); //默认是每个News类的toString方法返回值

    setListAdapter(adapter);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    Log.i(LOG_TAG, "onCreateView");
    return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    Log.i(LOG_TAG,"onActivityCreated");
    }

    @Override
    public void onStart() {
    super.onStart();
    Log.i(LOG_TAG,"onStart");
    }

    @Override
    public void onResume() {
    super.onResume();
    Log.i(LOG_TAG,"onResume");
    }

    @Override
    public void onPause() {
    super.onPause();
    Log.i(LOG_TAG, "onPause");
    }


    @Override
    public void onStop() {
    super.onStop();
    Log.i(LOG_TAG,"onStop");
    }

    @Override
    public void onDetach() {
    super.onDetach();
    Log.i(LOG_TAG, "onDetach");
    activityCallbacks=null;
    }



    @Override
    public void onDestroyView() {
    super.onDestroyView();
    Log.i(LOG_TAG, "onDestroyView");
    }

    @Override
    public void onDestroy() {
    super.onDestroy();
    Log.i(LOG_TAG, "onDestroy");
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);
            //由于多态性,直接调用子类中实现的该接口函数

    activityCallbacks.onItemSelect((int) id);

    Log.i(LOG_TAG,"onListItemClick"+"id:"+id);
    }

    }

    (3)NewsContentFragment.java

    package com.henry.usingfragment;

    import android.app.Fragment;
    import android.content.Context;
    import android.os.Bundle;
    import android.support.annotation.Nullable;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;

    /**
    * Created by shiyanshi on 2016/3/15.
    */
    public class NewsContentFragment extends Fragment {
    private final String TAG="NewsContentFragment";
    public static final String TAG_NEWS_ID= "com.henry.usingfragment";
    private News news;


    @Override
    public void onAttach(Context context) {
    super.onAttach(context);
    Log.i(TAG, "onAttach");
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Log.i(TAG,"onCreate");

    boolean isIllegal=getArguments().containsKey(TAG_NEWS_ID);
    if (isIllegal){
    int id=getArguments().getInt(TAG_NEWS_ID);
    news=NewsContent.getInstance().newsMap.get(id);
    }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    Log.i(TAG, "onSaveInstanceState");
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    Log.i(TAG, "onCreateView");
    Log.i(TAG, NewsContent.getInstance().newsMap.get(getArguments().getInt(TAG_NEWS_ID)).getTitle());

    View rootView=inflater.inflate(R.layout.news_content_layout,container,false);
    if (news!=null){
    ((TextView)rootView.findViewById(R.id.news_title)).setText(news.getTitle());
    ((TextView)rootView.findViewById(R.id.news_content)).setText(news.getContent());
    Log.i(TAG, "onCreateView---->内容更新成功");
    }

    return rootView;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    Log.i(TAG,"onActivityCreated");
    }
    }

    (4)News.java

    package com.henry.usingfragment;

    /**
    * Created by shiyanshi on 2016/3/15.
    */
    public class News {
    private int id;
    private String title;
    private String content;
    public News(int id,String title,String content){
    this.id=id;
    this.title=title;
    this.content=content;
    }

    public int getId() {
    return id;
    }

    public String getContent() {
    return content;
    }

    public String getTitle() {
    return title;
    }

    public void setId(int id) {
    this.id = id;
    }

    public void setContent(String content) {
    this.content = content;
    }

    public void setTitle(String title) {
    this.title = title;
    }

    //此处只返回了title,是为了和NewsTitleFragment中的ListAdapter相对应
    @Override
    public String toString() {
    return title;
    }
    }

    (5)NewsContent.java

    package com.henry.usingfragment;

    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;

    /**
    * Created by shiyanshi on 2016/3/15.
    */
    public class NewsContent {
    //单例模式
    private static NewsContent newsContent;
    public List<News> news;
    public Map<Integer,News> newsMap;

    //适用于单例模式,无法被外部访问,只能在内部调用
    private NewsContent(){
    news=new ArrayList<>();
    newsMap=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);

    newsMap.put(news1.getId(),news1);
    newsMap.put(news2.getId(),news2);
    newsMap.put(news3.getId(),news3);

    }

    //单例模式中,用来获取该类的静态实例
    public static NewsContent getInstance(){
    if (newsContent==null){
    newsContent=new NewsContent();
    }
    return newsContent;
    }
    }

    ( 6) 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="horizontal"
    tools:context="com.henry.usingfragment.MainActivity"
    android:divider="?android:dividerHorizontal"
    android:showDividers="middle">

    <fragment
    android:id="@+id/news_title_fragment"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:name="com.henry.usingfragment.NewsTitleFragment"/>
    <FrameLayout
    android:id="@+id/news_content_fargment_container"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="3">
    </FrameLayout>

    </LinearLayout>

    (7)news_content_layout.xml

    <?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:id="@+id/container"
    android:paddingLeft="20dp"
    android:paddingRight="20dp"
    android:orientation="vertical">
    <TextView
    android:id="@+id/news_title"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:layout_marginTop="20dp"
    android:background="@android:color/darker_gray"
    />
    <TextView
    android:id="@+id/news_content"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="3"
    android:layout_below="@id/news_title"
    android:layout_margin="20dp"
    android:background="@android:color/white"/>
    </LinearLayout>





  • 相关阅读:
    ASP.NET通用权限管理系统(FrameWork) 1.0.0 Release 发布
    ASP.NET通用权限管理系统(FrameWork) 1.0.3 Release
    ASP.NET通用权限管理系统(FrameWork) 之用户在线列表 泛型缓存 [原创]
    DDBuildToolsRelease1.0
    FineMessBox弹出窗口js (修改版,增加对Firefox支持)
    [开源]ASP.NET通用权限管理系统(FrameWork) 1.0.2 Release
    [开源]ASP.NET通用权限管理系统(FrameWork) 1.0.1 Release
    如何在CodePlex 创建开源项目
    今天上班遇到好人了
    ASP.NET通用权限管理系统(FrameWork) 在线演示地址
  • 原文地址:https://www.cnblogs.com/ql698214/p/5281001.html
Copyright © 2020-2023  润新知