Android Fragment 基本使用方法

2,145 阅读4分钟

Fragment 的含义

Fragment 表示 FragmentActivity 中的行为或界面的一部分。可以在一个 Activity 中组合多个片段,从而构建多窗格界面;也可以在多个 Activity 中重复使用某个片段。可以将 Fragment 视为 Activity 的模块化组成部分。

fragment 特点:

  • Fragment具有自己的生命周期,能接收自己的输入事件,并且可以在 Activity 运行时添加或移除片段(这有点像可以在不同 Activity 中重复使用的“子 Activity”)。
  • Fragment 必须始终托管在 Activity 中,其生命周期直接受宿主 Activity 生命周期的影响。
    1. 当 Activity 暂停时,Activity 的所有片段也会暂停;当 Activity 被销毁时,所有片段也会被销毁。
    2. 不过,当 Activity 正在运行(处于已恢复生命周期状态)时,可以独立操纵每个片段,如添加或移除 Fragment。当执行此类片段事务时,也可将其添加到由 Activity 管理的Back Stack中,Activity 中的每个Back Stack 条目都是一条已发生片段事务的记录。借助返回栈,用户可以通过按返回按钮回到上一个Fragment。
    3. Fragment 也有自己独立的Layout文件和class文件
    4. Fragment 和 Activity 是多对多的关系:一个 Fragment 可以包含在多个不同的Activity中,一个Activity中可以包含多个不同的Fragment

Fragment 使用方法

1. 生成 Fragment:

  1. 构造一个 Fragment 的子类
  2. 在这个子类中复写 onCreateView() 方法,在此方法中 通过 inflater 类调用layout文件生成一个 Fragment。

示例代码:

 @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_1,container,false);
        return view;
    }

2. 将 Fragment 添加到 Activity:

  1. 将 Fragment 作为 Activity 布局的一部分添加到 Activity 中,其位于 Activity 视图层次结构的某个 ViewGroup 中,并且 Fragment 会定义其自己的视图布局,可以在 Activity 声明一个 FramLayout 作为 Fragment 容器,利用 java 代码将其插入容器:
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_container);


        fragmentManager = getSupportFragmentManager();
        fragmentTransaction = fragmentManager.beginTransaction();

        if(findViewById(R.id.fl_Container1) != null){ //确认有一个Fragment容器

            if(savedInstanceState != null){ //如果activity是resumed,再生成一个Fragment会覆盖原来的Fragment
                return;
            }

            fragment_1 = new Fragment_1();
            //实例化一个自定义Fragment类的对象,并将此对象添加到容器Activity中
            fragmentTransaction.add(R.id.fl_Container1,fragment_1).commitAllowingStateLoss();
            //调用commit方法后才会生效,commitAllowingStateLoss宽容显示,允许一些横竖屏幕切换等情况下会出现的错误。
        }
    }
  1. 也可以通过在 Activity 的布局文件中声明 Fragment,将其作为 元素插入的 Activity 布局,或者通过将其添加到某个现有的 ViewGroup,具体代码如下:

     ` <fragment android:name = "fragment所在文件路径"/>`
    

如果用<fragment>方法添加到Activity,就无法在运行时移除或替换此Fragment。

3. 在运行过程中操作 Fragment

如要管理 Activity 中的片段,就需使用 FragmentManager。如要获取它,需要从 Activity 类中调用 getSupportFragmentManager() 方法。

使用 FragmentManager 执行的如下操作进行 Fragment 操作:

  1. 通过 findFragmentById()(针对在 Activity 布局中提供界面的片段)或 findFragmentByTag()(针对提供或不提供界面的片段)获取 Activity 中存在的片段。
  2. 通过 popBackStack()(模拟用户发出的返回命令)使片段从返回栈中弹出。
  3. 也可使用 FragmentManager 打开一个 FragmentTransaction,通过它来执行其他 Fragment 操作,如添加和移除片段。
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// Commit the transaction
transaction.commit();

Activity 与 Fragment,Fragment 与 Fragment 的通信

实现思路:

在 Fragment 类中定义一个回调接口,并要求宿主 Activity 实现此接口。当 Activity 通过该接口收到回调时,可根据需要与 Activity 或布局中的其他 Fragment 共享这些信息。

Activity 与 Fragment 通信:

  1. 在 Fragment 中定义回调接口,在接口中定义的方法是通信的具体实现方法。
 public interface onMessageReader {
            public void onMessageReade(String message);
        }
  1. 在宿主 Activity 中实现回调接口,并复写接口中的方法。
 @Override
    public void onMessageReade(String message) {
        mTvmessage = findViewById(R.id.tv_message);
        mTvmessage.setText(message);
    }
  1. 利用 Fragment 类中的 onAttach() 回调函数,此函数在 Fragment 被添加到宿主 Activity 时会返回此 Activity 对象,利用此对象实例化一个回调接口,这样就可以通过这个实例实现 Fragment 和 Activity的通信。同时通过try catch 结构保证宿主已经实现了回调接口。
     @Override
        public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        Activity activity = (Activity) context;


        //使用onAttach方法传过来的context参数实例化接口,使用此接口内的函数在Fragment和Activity之间通信
        try {  //check实现接口是是否override了Read方法
            onMessageReader = (Fragment_1.onMessageReader) activity;
        }catch (ClassCastException e){
            throw new ClassCastException(activity.toString() + "must override onMessageReader...");
        }
    }

Fragment 与 Fragment 之间的通信:

Fragment 之间是无法直接通信的,只有同一个宿主 Activity 下的 Fragment 之间可以借助宿主实现通信,具体实现方法建立在 Fragment 和 Activity 的通信之上,在实现回调接口中的通信方法时,构造一个 Bundle 类的对象,将 Fragment A 的信息以键值对的方式传送给 Bundle 对象,最后调用 Fragment 类的 setArgumnet() 方法将信息传送给 Fragment B ,Fragment B 调用 getArgument() 方法就可以取出信息使用。

 @Override
    public void onMessageReade(String message) {
    
        Fragment_2 fragment_2 = new Fragment_2();
        fragmentManager.beginTransaction().add(R.id.fl_Container3,fragment_2).commit();
        Bundle bundle =  new Bundle();
        bundle.putString("Title",message);
        fragment_2.setArguments(bundle);
    }