美文网首页
Android——Fragment

Android——Fragment

作者: pkqgo | 来源:发表于2017-11-23 22:33 被阅读0次

    描述

    Fragment必须总是被嵌入到一个activity之中,并且fragment的生命周期直接接受其宿主activity的生命周期的影响。你可以认为fragment是activity的一个模块零件,它有自己的生命周期,接收它自己的输入的事件,并且可以在activity运行时添加或者删除。

    应该将每一个fragment设计为模块化和可复用化的activity组件。也就是说,你可以在多个activity中引用同一个fragment,因为fragment定义了它自己的布局,并且使用它本身生命周期回调的行为。

    生命周期

    图片.png

    Fragment比Activity多了几个额外的生命周期回调方法:

    onAttach(Activity):当Fragment和Activity发生关联时使用。
    
    onCreateView(LayoutInflater,ViewGroup,Bundle):创建该Fragment的视图
    
    onActivityCreate(Bundle):当Activity的onCreate()方法返回时调用
    
    onDestoryView():与onCreateView相对应,当该Fragment的视图被移除时调用
    
    onDetach():与onAttach()相对应,当Fragment与Activity关联被取消时调用
    
    注意:除了onCreateView()方法,其他的所有的方法如果你重写了,必须调用父类对于该方法的实现
    

    管理fragment生命周期与管理activity生命周期很相像,像activity一样,fragment也有三种状态:
    1、Resumed:
    fragment在运行中的activity中可见。

    2、Paused:
    另一个activity处于前台且得到焦点,但是这个fragment所在的activtiy仍然可见(前台activity部分透明,或者没有覆盖全屏)。

    3、Stopped:
    fragment不可见。要么宿主activity已经停止,要么fragment已经从activity上移除,但已被添加到后台栈中。一个停止的fragment仍然活着(所有的状态和成员信息仍然由系统保留着)。但是,它对于用户来讲已经不再可见,并且如果activity被杀掉,它也将被杀掉。

    Fragment持久化

    如果activity的进程被杀掉了,在activity被重新创建时,你恢复fragment状态。可以执行fragment的onSaveIntanceState()来保存状态(注意:fragment是在onCreate(),onCreateView()或者onActivityCreate()中进行恢复)。

    在生命周期方面,activity和fragment之间一个很重要的不同就是在各自的后台栈中是如何存储的。当activity停止时,默认情况下activity被安置在由系统管理的activity后台栈中;fragment仅当在一个事务被移除时,通过显式调用addToBackStack()请求保存的实例,该fragment才被置于由宿主activity管理的后台栈。

    使用方法

    静态使用:直接在xml文件中使用 fragment标签
    <RelativeLayout 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" >
                 <fragment
                      android:id="@+id/id_fragment_title"
                      android:name="com.zhy.zhy_fragments.TitleFragment"//直接对应Fragment类
                      android:layout_width="fill_parent"
                      android:layout_height="45dp" />
                 <fragment
                      android:layout_below="@id/id_fragment_title"
                      android:id="@+id/id_fragment_content"
                      android:name="com.zhy.zhy_fragments.ContentFragment"
                      android:layout_width="fill_parent"
                      android:layout_height="fill_parent" />
    </RelativeLayout>
    
    动态使用
           add()、replace()、remove()、hide()、show()
           getSupportFragmentManager().beginTransaction().add(R.id.content, new FirstFragment())
                            .commit();
    

    API介绍

        //根据ID来找到对应的Fragment实例,主要用在静态添加fragment的布局中,因为静态添加的fragment才会有ID
        1、fragmentManager.findFragmentById();
    
        //根据TAG找到对应的Fragment实例,主要用于在动态添加的fragment中,根据TAG来找到fragment实例
        2、fragmentManager.findFragmentByTag();
    
        //获取所有被ADD进Activity中的Fragment
        3、fragmentManager.getFragments();
    
        //替换containerViewId中的fragment实例,注意,它首先把containerViewId中所有fragment删除,然后再add进去当前的fragment
        4、replace(int containerViewId, Fragment fragment);
    
        //将一个fragment实例添加到Activity容器的最上层
        5、add(int containerViewId, Fragment fragment, String tag);
    
        //从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈,这个Fragment实例将会被销毁。
        6、remove(Fragment fragment);
    
        //隐藏当前的Fragment,仅仅是设为不可见,并不会销毁
        7、hide(Fragment fragment)
    
        //显示之前隐藏的Fragment
        8、show(Fragment fragment)
    

    Fragment回退栈

    类似与Android系统为Activity维护一个任务栈,我们也可以通过Activity维护一个回退栈来保存每次Fragment事务发生的变化。

    如果你将Fragment任务添加到回退栈,当用户点击后退按钮时,将看到上一次的保存的Fragment。一旦Fragment完全从后退栈中弹出,用户再次点击后退键,则退出当前Activity。

          //添加方法
           fragmentTransaction.addToBackStack(String)
    
           ex:
            FragmentTwo fTwo = new FragmentTwo();
            FragmentManager fm = getFragmentManager();
            FragmentTransaction tx = fm.beginTransaction();
            tx.replace(R.id.id_content, fTwo, "TWO");
            tx.addToBackStack(null);
            tx.commit();
    
    把FragmentTwo加入回退栈,再使用replace方法替换,
    由于FragmentTwo加入回退栈,之前加入的FragmentOne实例不会被销毁。
    

    在创建Fragment时要传入参数

    通过Arguments创建Fragment,不建议通过为Fragment添加带参数的构造函数

        public class ContentFragment extends Fragment  {
            private String mArgument;
            public static final String ARGUMENT = "argument";
    
            @Override
            public void onCreate(Bundle savedInstanceState)          {
                super.onCreate(savedInstanceState);
                // mArgument = getActivity().getIntent().getStringExtra(ARGUMENT);
                Bundle bundle = getArguments();
                if (bundle != null)
                    mArgument = bundle.getString(ARGUMENT);
            }
    
            /**
             * 传入需要的参数,设置给arguments
             * @param argument
             * @return
             */
            public static ContentFragment newInstance(String argument)          {
                Bundle bundle = new Bundle();
                bundle.putString(ARGUMENT, argument);
                ContentFragment contentFragment = new ContentFragment();
                contentFragment.setArguments(bundle);
                return contentFragment;
            }
        }
    

    Fragment、Viewpager、懒加载

    1、FragmentPagerAdapter:对于不再需要的fragment,选择调用detach方法,仅销毁视图,并不会销毁fragment实例。

    2、FragmentStatePagerAdapter:会销毁不再需要的fragment,当当前事务提交以后,会彻底的将fragment从当前Activity的FragmentManager中移除。

    3、懒加载,核心方法是 setUserVisibleHint()

    public class BaseLazyLoadFragment extends Fragment {
    
        private boolean mIsInit = false;//数据是否加载完成
        private boolean mIsPrepared = false;//UI是否准备完成
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View mRootView = inflater.inflate(R.layout.fragment_first, container, false);
            mIsPrepared = true;
            lazyLoad();
            return mRootView;
        }
    
        @Override
        public void setUserVisibleHint(boolean isVisibleToUser) {
            super.setUserVisibleHint(isVisibleToUser);
            if (isVisibleToUser) {
                lazyLoad();
            }
        }
    
        public void lazyLoad() {
            if (getUserVisibleHint() && mIsPrepared && !mIsInit) {
                // 异步初始化,在初始化后显示正常UI
                loadData();
            }
        }
    
        private void loadData() {
            new Thread() {
                public void run() {
                    // 1. 加载数据
                    // 2. 更新UI
                    // 3. mIsInit = true
                    mIsInit = true;
                }
            }.start();
        }
        
    }
    
    

    多个Fragment重叠

    原因1:横竖屏切换,造成Fragment重新实例化。
    原因2:按下Home键,Activity处于后台,由于内存不足被销毁,重新唤醒时Fragment重新实例化。

    注:出现的原因是在 API24 之前的 v4包 的源码问题,
    解决方案:通过检查onCreate的参数Bundle savedInstanceState就可以判断,当前是否发生Activity的重新创建:

    默认的savedInstanceState会存储一些数据,只有在savedInstanceState==null时,才进行创建Fragment实例:

    public class MainActivity extends Activity {
        private static final String TAG = "FragmentOne";
        private FragmentOne mFOne;
    
        @Override
        protected void onCreate(Bundle savedInstanceState)  {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            if(savedInstanceState == null)   {
                mFOne = new FragmentOne();
                FragmentManager fm = getFragmentManager();
                FragmentTransaction tx = fm.beginTransaction();
                tx.add(R.id.id_content, mFOne, "ONE");
                tx.commit();
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:Android——Fragment

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