Android日记之Fragment的基本使用

作者: 居居居居居居x | 来源:发表于2019-11-10 16:40 被阅读0次

    前言

    (本篇基于Fragment基本使用,因为此篇总结的很好,我就基于此篇文章再写一些关于自己的理解)
    Fragment,一般称之为碎片,是在Android 3.0出现的,Fragment是一种可以嵌入在活动中的UI片段,能够让程序更加合理和充分地利用大屏幕的空间,出现的初衷是为了适应大屏幕的平板电脑,官方对Fragment的定义是:

    • Fragment依赖于Activity,不能独立存在。
    • 一个Activity可以有多个Fragment。
    • 一个Fragment可以被多个Activity重用。
    • Fragment有自己的生命周期,并能接收输入事件。
    • 可以在Activity运行时动态地添加或删除Fragment。

    Fragment也是我们最常使用的组件,使用的频率可谓是非常的高,它也有以下几点优势:

    • 模块化(Modularity):我们不必把所有代码全部写在Activity中,而是把代码写在各自的Fragment中。
    • 可重用(Reusability):多个Activity可以重用一个Fragment。
    • 可适配(Adaptability):根据硬件的屏幕尺寸、屏幕方向,能够方便地实现不同的布局,这样用户体验更好。

    Fragment生命周期

    (此段来源于Fragment基本使用,因为这篇文章对于Fragment的生命周期总结的很好,参考这个就好了)

    Fragment的生命周期
    Fragment的一般生命周期如上图所示:
    • onAttach():Fragment和Activity相关联时调用。可以通过该方法获取Activity引用,还可以通过getArguments()获取参数。
    • onCreate():Fragment被创建时调用
    • onActivityCreated():当Activity完成onCreate()时调用
    • onStart():当Fragment可见时调用。
    • onResume():当Fragment可见且可交互时调用
    • onPause():当Fragment不可交互但可见时调用。
    • onStop():当Fragment不可见时调用。
    • onDestroyView():当Fragment的UI从视图结构中移除时调用。
    • onDestroy():销毁Fragment时调用。
    • onDetach():当Fragment和Activity解除关联时调用。

    Fragment生命周期会经历:运行、暂停、停止、销毁。

    • 运行状态:碎片可见时,关联活动处于运行状态,其也为运行状态
    • 暂停状态:活动进入暂停状态,相关联可见碎片就会进入暂停状态
    • 停止状态:活动进入停止状态,相关联碎片就会进入停止状态,或者通过FragmentTransaction的remove()replace()方法将碎片从从活动中移除,但如果在事务提交之前调用addToBackStack()方法,这时的碎片也会进入到停止状态。
    • 销毁状态:当活动被销毁,相关联碎片进入销毁状态。或者调用FragmentTransaction的remove()replace()方法将碎片从活动中移除,但在事务提交之前并没有调用addToBackStack()方法,碎片也会进入到销毁状态。

    Fragment的使用

    在使用Fragment的时候,先介绍以及会用到的核心类:

    • Fragment:Fragment的基类,任何创建的Fragment都需要继承该类。
    • FragmentManager:管理和维护Fragment。他是抽象类,具体的实现类是FragmentManagerImpl。
    • FragmentTransaction:对Fragment的添加、删除等操作都需要通过事务方式进行。他是抽象类,具体的实现类是BackStackRecord。

    开发Fragment不建议使用android.app下的Fragment而应是android:support.v4.app,因为support库是不断更新的。Fragment使用方式有有两种,静态使用和动态使用,我们先来看看静态使用。

    1. 静态使用

    • 创建一个Fragment以及对应的XML布局文件。

    • 在创建的这个Fragment类中的onCreate()中通过inflater去注册布局文件,然后并返回这个布局的view。

    • 在需要加载这个Fragment的Activity中的布局文件添加fragment控件,通过name添加Fragment,控件的id也一定要添加,否则运行会报错。


      Fragment添加报错,错误里也说的很清楚了

    首先创建一个Fragment,我们可以直接通过Android Stuodio进行创建,在你需要的位置右键新建选择Fragment(Blank)。


    Fragment创建

    这里我们发现下面有两个打钩选项,看意思就知道,第1个是是否创建工程方法,第2个是是否创建这个Fragment的回调接口,我们这里2个都不选,创建完毕就会生成对应的Fragment和XML文件了。

    
    //TestFragment的Fragment文件
    public class TestFragment extends Fragment {
    
    
        public TestFragment() {
            // Required empty public constructor
        }
    
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            // Inflate the layout for this fragment
            return inflater.inflate(R.layout.fragment_test, container, false);
        }
    
    }
    
    
    //TestFragment的XML文件
    <?xml version="1.0" encoding="utf-8"?>
    <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"
        tools:context=".TestFragment">
    
        <!-- TODO: Update blank fragment layout -->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="这是Fragment" />
    
    </FrameLayout>
    

    然后我们在Activity中声明fragmen控件,然后就可以运行了。

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        tools:context=".MainActivity">
    
        <fragment
            android:id="@+id/testFrag"
            android:name="com.ju.fragmentdemo.TestFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    
    </LinearLayout>
    
    Fragment测试运行结果
    静态使用的缺点很明显,位置是固定的,不能删除,所以基本很少使用。

    2.动态使用

    • 首先通过getSupportFragmentManager()方法获取FragmentManager对象。

    • 接着通过FragmentManager的beginTransaction()来开启一个事务,获得FragmentTransaction对象。

    • 调用FragmentTransaction的add()或者repalce()方法来加载Fragment。

    • 最后调用commit()方法提交完毕。

    我们还是老样子,先创建一个Fragment,因为刚刚已经创建过了,我们就用那个Fragment就行,然后把Activity布局上的Fragment删除,这里我们需要一个布局控件来去替换这个Fragment,我们这里就可以直接把LinearLayout来替换掉,我们给他声明个id,然后在Activity的onCreate()写入方法。

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/lin_test"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        tools:context=".MainActivity">
    
    </LinearLayout>
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            transaction.add(R.id.lin_test,new TestFragment());
            transaction.commit();
        }
    }
    
    动态使用Fragment

    这里说几点,在动态的加载Fragment中,FragmentTransaction是有提供各种方法来完成增删改等操作,完成后使用commit()方法就可以。

    • transaction.add():往Activity里面添加一个片段
    • transaction.remove():从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈,这个+ Fragment实例将会被销毁
    • transaction.replace():使用另一个Fragment替换当前的,实际上是remove()然后add()的合体
    • transaction.hide():隐藏当前Fragment,仅不可见,不会销毁
    • transaction.show():显示之前隐藏的Fragment
    • detach():会将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护
    • attach():重建view视图,附加到UI上并显示。

    Fragment和Activity传递数据

    有时候是需要将数据传递给Fragment的,但是不太推荐直接通过构造函数去进行传递,而且Fragment和Activity的互相传递方式也有不同。

    1. Activity传递给Fragment

    在Activity创建一个Bundle,把要传入的数据放入Bundle中,然后通过Fragment的setArguments()把Bundle设置进去,最后在Fragment中使用getArguments()来获取Bundle对象,就可以获取传递过来的值了。

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //创建Bundle
            Bundle bundle = new Bundle();
            bundle.putString("key","传递的值");
    
            TestFragment testFragment = new TestFragment();
            testFragment.setArguments(bundle);
    
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            transaction.add(R.id.lin_test,testFragment);
            transaction.commit();
        }
    }
    
    
    public class TestFragment extends Fragment {
    
    
        private TextView textView;
    
        public TestFragment() {
            // Required empty public constructor
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            // Inflate the layout for this fragment
            return inflater.inflate(R.layout.fragment_test, container, false);
        }
        
        //在这里获取
        @Override
        public void onActivityCreated(@Nullable Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            textView =  getView().findViewById(R.id.text);
            Bundle bundle = getArguments();
            textView.setText(bundle.getString("key"));
        }
    }
    
    通过Bundle获取值
    还有一种办法就是通过onAttach()方法来强转。
    //Activity创建一个函数,可以设置要传入的值
    public String getValue(){
        return "这里是传给Fragment的值";
    }
    
    //然后我们在Fragment的onAttach方法这样写,获取的值设置到控件上
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        value = ((MainActivity)context).getValue();
    }
    
    通过onAttach()结果

    2. Fragment传递给Activity

    这里我们可以使用接口回调来传递数据,也可以使用EventBus来进行传递,接口回调传递数据的代码如下。

    //设置个接口
    public interface Listener {
        
        void getValue(String v);
    }
    
    //在Fragment里面进行如下代码
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        //设置传给Activity的值
        listener.getValue("hello");
    }
    
    
    @Override
    public void onAttach(Context context) {
        listener =  ((Listener)context);
        super.onAttach(context);
    }
    
    //Activit继承这个接口,接收回调过来的参数。
    @Override
    public void getValue(String v) {
        Toast.makeText(this, "已收到Fragment的消息:--" + v + "--,客气了", Toast.LENGTH_SHORT).show();
    }
    
    传给Activity结果

    参考

    相关文章

      网友评论

        本文标题:Android日记之Fragment的基本使用

        本文链接:https://www.haomeiwen.com/subject/fhvnbctx.html