美文网首页
Fragment学习笔记(基础篇)

Fragment学习笔记(基础篇)

作者: 含笑小基石 | 来源:发表于2017-07-27 17:08 被阅读0次

    Fragment学习笔记

    一、Fragment的定义

    Fragment是在Android 3.0才开始引入的,它能让app在现有基础上性能大幅度提高,占用的内存降低,同样的界面,Fragment要比Activity占用的内存少,响应速度Fragment也要比Activty快(可能现在的手机CPU处理速度都很快,所以没什么感觉),"单Activity + 多Fragment架构"和"多模块Activity + 多Fragment架构"的开发模式也已经成为了现在的主流。

    二、Fragment的使用

    1.新建fragment_one.xml布局,加入一个Button

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <Button
            android:id="@+id/button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Button" />
    </LinearLayout>
    

    2.新建OneFragment,重写onCreateView()方法,将fragment动态加载进来。

    public class OneFragment extends Fragment {
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fragment_one, container, false);
            return view;
        }
    }
    

    3.修改activity_main.xml文件,使用一个FrameLayout作为父级容器。

    <?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">
    
        <FrameLayout
            android:id="@+id/one_fragment"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    
    </LinearLayout>
    

    4.修改MainActivity,通过getSupportFragmentManager()获取FragmentManager,调用beginTransaction()开启一个事务,调用add()或者replace()添加fragment,最后调用commit()提交事务。

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            if (savedInstanceState ==null) {
                getSupportFragmentManager()
                    .beginTransaction()
                    .add(R.id.one_fragment, new OneFragment())
                    .commit();
            }
        }
    }
    
    

    这样我们就实现了一个activity+一个fragment的实例,接下来我们通过这个fragment的button来启动另一个fragment。

    image.png

    5.新建fragment_two.xml文件,加入一个TextView和Button

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="TwoFragment"
            android:textSize="30sp"/>
    
        <Button
            android:id="@+id/back_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Back" />
    
    
    </LinearLayout>
    

    6.新建TwoFragment类,重写onCreateView()引入布局。

    public class TwoFragment extends Fragment{
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            final View root = inflater.inflate(R.layout.fragment_two, container, false);
            return root;
        }
    }
    

    7.修改OneFragment的代码,通过View来设置button的点击事件,调用FragmentManager来切换fragment。

    public class OneFragment extends Fragment {
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fragment_one, container,false);
            view.findViewById(R.id.open_btn).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    getFragmentManager()
                    .beginTransaction()
                    .replace(R.id.replace_fragment, new TwoFragment())
                    .commit();
                }
            });
            return view;
        }
    }
    
    

    这样我们就实现了在一个FrameLayout的父容器内进行fragment的切换。但是我们发现当我们到TwoFragment的时候点击back键程序直接退出了,这时候我们可以修改代码来解决这个问题。

    image.png

    8.修改OneFragment的代码,调用transaction.addToBackStack(null),将Fragment加入到回退栈。这样点击back键就能回到上一个fragment。

    public class OneFragment extends Fragment {
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fragment_one, container,false);
            view.findViewById(R.id.open_btn).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    getFragmentManager()
                        .beginTransaction()
                        .addToBackStack(null)
                        .replace(R.id.replace_fragment, new TwoFragment())
                        .commit();
                }
            });
            return view;
        }
    }
    

    9.也可以自己设置主动回退键,设置TwoFragment的button点击事件

    public class TwoFragment extends Fragment{
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            final View root = inflater.inflate(R.layout.fragment_two, container, false);
            root.findViewById(R.id.back_btn).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    getFragmentManager().popBackStack();
                }
            });
            return root;
        }
    }
    

    三、Fragment的生命周期

    image

    生命周期分析:

    1.当一个fragment被创建的时候,它会经历以下状态.

    • onAttach()
    • onCreate()
    • onCreateView()
    • onActivityCreated()

    2.当这个fragment对用户可见的时候,它会经历以下状态。

    • onStart()
    • onResume()

    3.当这个fragment进入“后台模式”的时候,它会经历以下状态。

    • onPause()
    • onStop()

    4.当这个fragment被销毁了(或者持有它的activity被销毁了),它会经历以下状态。

    • onPause()
    • onStop()
    • onDestroyView()
    • onDestroy()
    • onDetach()

    四、Fragment的切换

    我们在android开发中经常会用到fragment,例如侧拉栏的切换,viewPager的切换。
      而我们切换fragment无非就两种方法:

    1.replace();

    2.add(),hide(),show();

    两种发方法相比较而言,我更加推荐使用第二种方法,因为fragment执行add()后进行show()和hide()只会执行onDestroyView()去销毁fragment的视图,而fragmentTanslation的replace()方法实际上就是remove()和add()的结合,每一次fragment的切换都要重新onCreate()创建一个fragment实例,这样对于性能上来说不是很好。

    以下是使用第二种切换fragment方法的函数:

    private void changeFragment(Fragment fromFragment, Fragment toFragment) {  
      
        if (nowFragment != toFragment) {  
            nowFragment = toFragment;  
        }  
      
        FragmentManager fm = getSupportFragmentManager();  
        FragmentTransaction ft = fm.beginTransaction();  
      
        if (toFragment.isAdded() == false) {  
            ft.hide(fromFragment).add(R.id.center_view_main_activity, toFragment).commit();  
        } else {  
            ft.hide(fromFragment).show(toFragment).commit();  
        }  
      
    }  
    

    五、TabLayout+ViewPager+Fragment的实战

    1.新建工程项目,在activity_main.xml文件中加入TabLout和ViewPager控件,要引入相关的依赖库。

    <?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:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.kingdee.zhao.viewpagerfragmenttest.MainActivity">
    
    
        <android.support.design.widget.TabLayout
            android:id="@+id/activity_tab"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabIndicatorColor="@color/colorAccent"
            app:tabSelectedTextColor="@color/colorAccent"
            app:tabTextColor="@color/colorPrimaryDark">
    
        </android.support.design.widget.TabLayout>
    
        <android.support.v4.view.ViewPager
            android:id="@+id/activity_vp"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    
    </LinearLayout>
    
    

    2.这次的实践准备写三个fragment页面,所以需要三个Fragment,因为三个fragment里面的代码会基本一致,为了不让代码重复使用,我们新建一个BaseFragment的抽象类来整合代码。

    public abstract class BaseFragment extends Fragment {
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view = inflater.inflate(getLayoutId(), container, false);
            view.findViewById(getImageId()).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(getActivity(), getToastString(), Toast.LENGTH_SHORT).show();
                }
            });
            return view;
        }
    
        protected abstract String getToastString();
    
        protected abstract int getImageId();
    
        protected abstract int getLayoutId();
        
    }
    public abstract class BaseFragment extends Fragment {
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view = inflater.inflate(getLayoutId(), container, false);
            view.findViewById(getImageId()).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(getActivity(), getToastString(), Toast.LENGTH_SHORT).show();
                }
            });
            return view;
        }
    
        protected abstract String getToastString();
    
        protected abstract int getImageId();
    
        protected abstract int getLayoutId();
        
    }
    

    3.然后剩下的三个Fragment的代码就基本一致了,实现BaseFragment的三个抽象方法,传入对应的参数就行了,拿其中一个举例:

    public class VolleyballFragment extends BaseFragment {
        @Override
        protected String getToastString() {
            return "算了,还是去打排球吧!";
        }
    
        @Override
        protected int getImageId() {
            return R.id.img_pingpong;
        }
    
        @Override
        protected int getLayoutId() {
            return R.layout.fragment_pingpong;
        }
    }
    

    4.因为我们要使用到ViewPager来管理Fragment,所以我们需要新建一个继承自FragmentPagerAdapter的适配器MyAdapter来对两者进行绑定。

    public class MyAdapter extends FragmentPagerAdapter {
    
        private ArrayList<String> titleList;
        private ArrayList<Fragment> fragmentList;
    
        public MyAdapter(FragmentManager fm, ArrayList<String> titleList, ArrayList<Fragment> fragmentList) {
            super(fm);
            this.titleList = titleList;
            this.fragmentList = fragmentList;
        }
    
        @Override
        public Fragment getItem(int position) {
            return fragmentList.get(position);
        }
    
        @Override
        public int getCount() {
            return titleList.size();
        }
    
        @Override
        public CharSequence getPageTitle(int position) {
            return titleList.get(position);
        }
    }
    

    5.最后处理MainActivity文件,用两个ArrayList容器来装载Title和Fragment的数据,实例化TabLayout和ViewPager,并为两者设置adapter适配数据。

    public class MainActivity extends AppCompatActivity {
    
        private TabLayout tabLayout;
        private ViewPager viewPager;
        private MyAdapter adapter;
    
        private ArrayList<String> titleList = new ArrayList<String>() {
            {
                add("Pingpong");
                add("Swimming");
                add("Volleyball");
            }
        };
    
        private ArrayList<Fragment> fragmentList = new ArrayList<Fragment>() {
            {
                add(new PingpongFragment());
                add(new SwimmingFragment());
                add(new VolleyballFragment());
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            initView();
    
            setView();
        }
    
        private void initView() {
            tabLayout = findViewById(R.id.activity_tab);
            viewPager = findViewById(R.id.activity_vp);
            adapter = new MyAdapter(getSupportFragmentManager(), titleList, fragmentList);
        }
    
        private void setView() {
            viewPager.setAdapter(adapter);
            tabLayout.setupWithViewPager(viewPager);
        }
    }
    

    至此,我们的ViewPager+TabLayout+Fragment的实践就完成了,让我们来看一下效果图:

    image.png

    相关文章

      网友评论

          本文标题:Fragment学习笔记(基础篇)

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