博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Fragment的基本使用
阅读量:3779 次
发布时间:2019-05-22

本文共 14486 字,大约阅读时间需要 48 分钟。

Fragment的基本使用

一、Fragment的静态使用

Fragment可以在布局中直接使用<fragment>标签,使用android:name属性或者使用class属性来指定对应的Fragment实现。

activity_fragment_static.xml布局文件

Activity中就直接使用布局就可以。

public class FragmentTestActivity extends Activity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fragment_static);//直接使用布局就好 }}

二、Fragment的动态使用

Fragment除了在xml中使用<fragment>标签来指定Fragment外,还可以直接通过代码的形式来动态添加Fragment到xml布局中。

动态添加Fragment到xml中,需要借助FrameLayout布局,具体实现方式,看下面代码。

activity_fragment_dynamic.xml布局文件

FragmentTestActivity中动态使用Fragment替换FrameLayout

public class FragmentTestActivity extends Activity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fragment_dynamic); dynamicAddFragment(); } /** * 动态的使用Fragment */ private void dynamicAddFragment() { FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction transaction = fragmentManager.beginTransaction(); // 使用LiftCycleFragment替换指定的 id 的 View transaction.replace(R.id.content_dynamic_fragment, new DynamicFragment()); transaction.commit(); }}

三、Fragment的生命周期

Fragment是依附于Activity的,所以生命周期和Activity很多是保持一致的。当然也有一些不同的地方,让我们来看看吧。

Fragment的生命周期图:

image

Fragment的生命周期和Activity的生命周期对比图

image

对于对象的创建和销毁问题,最好保持在2个相对应的生命周期中


四、Fragment && FragmentManager && FragmentTransaction 常用API介绍

Fragment的API介绍:

//  通过bundle传递数据,后面会将用法setArguments(Bundle bundle);getArguments();// 判断Fragment状态isAdded();isDetached();isVisible();isHidden();isInLayout();isResumed();isRemoving();// 获取Fragment的标记和idgetId();getTag();//API 15getUserVisibleHint();setUserVisibleHint(true);// API 17getChildFragmentManager();getParentFragment();除了上述方法,还有Activity中的一些方法的封装和动画相关的方法。例如关于MenuItem,Permission,动画等,这里列举几个。如:MenuItem相关:setHasOptionsMenu(boolean b);onCreateOptionsMenu(Menu menu, MenuInflater inflater);onOptionsItemSelected(MenuItem item);Permission相关:requestPermissions(String[] permissions, int requestCode);onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults);shouldShowRequestPermissionRationale(String permission);动画相关:API 21setEnterTransition(Transition transition);setExitTransition(Transition transition);setAllowEnterTransitionOverlap(boolean allow);setAllowReturnTransitionOverlap(boolean allow);

FragmentManager介绍:

getFragmentManager();// 获取FragmentManager方法findFragmentById();// 通过id获取对应的FragmentfindFragmentByTag();// 通过Tag获取对应的FragmentbeginTransaction();// 开启事务,返回FragmentTransaction对象popBackStack();// 退出栈顶的Fragment//退出指定id的FragmentpopBackStack(int id , int flag);// flag: 0 or FragmentManager.POP_BACK_STACK_INCLUSIVEpopBackStack(String tag , int flag);//退出指定Tag的FragmentpopBackStackImmediate();// 返回一个boolean值popBackStackImmediate(int id , int flag);popBackStackImmediate(String tag , int flag);getBackStackEntryCount();// 获取返回栈中的数量addOnBackStackChangedListener(); // 添加返回栈改变的监听removeOnBackStackChangedListener();// 移除返回栈的监听isDestroyed();// API 17  是否Activity走了OnDestory()生命周期方法

FragmentTransaction介绍:

FragmentTransaction是一个抽象类,具体的是现实类是

BackStackRecord

常用API:

// 添加add(Fragment fragment, String tag);add(int containerViewId, Fragment fragment);add(int containerViewId, Fragment fragment,String tag);// 替换,相当于remove之后再addreplace(int containerViewId, Fragment fragment);replace(int containerViewId, Fragment fragment,String tag);// 移除remove(Fragment fragment);// 显示show(Fragment fragment);//隐藏hide(Fragment fragment);//依附attach(Fragment fragment);//分离detach(Fragment fragment);isEmpty();addToBackStack(String name);// 添加到任务栈,参name:null或者一个标记tag// 提交事务 API的具体差异,看源码解释commit();commitAllowingStateLoss();// 这是危险的,因为如果活动需要稍后从其状态恢复,则提交可能丢失commitNow();commitNowAllowingStateLoss();

五、Fragment的通信

Fragment常常会和ActivityFragment会有数据传递,那么如何实现呢

实现方式肯定有多种,就举例说下setArguments(Bundle bundle)的方式传递消息:

public class ArgumentFragment extends Fragment {
private String message; /** * 这种写法就是为了Activity或Fragment等向当前的Fragment传递消息 */ public static ArgumentFragment getInstance(String message) { //通过Bundle传递消息 Bundle bundle = new Bundle(); bundle.putString("message", message); ArgumentFragment fragment = new ArgumentFragment(); fragment.setArguments(bundle); return fragment; } @Override public void onAttach(Context context) { super.onAttach(context); //获取bundle传递的消息 Bundle bundle = getArguments(); if (bundle != null) { message = bundle.getString("message"); } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_lift_cycle, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); TextView textView = (TextView) view.findViewById(R.id.fragmnet_content_text); if (!TextUtils.isEmpty(message)) { textView.setText("ArgumentFragment message: "+message); } else { textView.setText("ArgumentFragment message is none"); } }}

Activity中的调用:

public class FragmentTestActivity extends Activity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fragment); FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction transaction = fragmentManager.beginTransaction(); // 建议使用(不要直接new对象),这样可以传递信息给Fragment transaction.replace(R.id.content_dynamic_fragment, ArgumentFragment.getInstance("Argument")); transaction.commit(); }}

六、Fragment的回退栈

添加到Fragment返回栈是通过transaction.addToBackStack(String name)方法,按返回键是,会从栈中一个个的退出。如果需要主动退出栈,可以调用fragmentManager.popBackStack()退出返回栈。具体我们看代码:

public class FragmentTestActivity extends Activity {
String[] tags = {
"One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fragment); createFragment(0, false); } private void createFragment(final int i, boolean addBackStace) { if (i >= tags.length) { return; } FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction transaction = fragmentManager.beginTransaction(); BackStackFragment fragment = BackStackFragment.getInstance(tags[i]); fragment.setFragmentClickListener(new FragmentClickListener() { @Override public void onFragmentClick() { createFragment(i + 1, true); } }); transaction.replace(R.id.content_dynamic_fragment, fragment, tags[i]); if (addBackStace) { transaction.addToBackStack(tags[i]); } transaction.commit(); } @Override protected void onResume() { super.onResume(); computeClearBackStack(false); } @Override protected void onPause() { super.onPause(); computeClearBackStack(true); } private void computeClearBackStack(boolean clean) { FragmentManager fragmentManager = getFragmentManager(); int backStackEntryCount = fragmentManager.getBackStackEntryCount(); Log.e("FragmentTestActivity", "onPause--> backStackEntryCount: " + backStackEntryCount); for (int i = 0; i < backStackEntryCount; i++) { FragmentManager.BackStackEntry backStackEntryAt = fragmentManager.getBackStackEntryAt(i); String name = backStackEntryAt.getName(); Log.e("FragmentTestActivity", "onPause--> name: " + name); if (clean) { fragmentManager.popBackStack(name, FragmentManager.POP_BACK_STACK_INCLUSIVE); } } }}

BackStackFragment

public class BackStackFragment extends Fragment {
private String message; private FragmentClickListener listener; public void setFragmentClickListener(FragmentClickListener listener) { this.listener = listener; } public static BackStackFragment getInstance(String message) { //通过Bundle传递消息 Bundle bundle = new Bundle(); bundle.putString("message", message); BackStackFragment fragment = new BackStackFragment(); fragment.setArguments(bundle); return fragment; } @Override public void onAttach(Context context) { super.onAttach(context); //获取bundle传递的消息 Bundle bundle = getArguments(); if (bundle != null) { message = bundle.getString("message"); } if (message == null) { message = ""; } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_content, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); TextView textView = (TextView) view.findViewById(R.id.fragmnet_content_text); if (!TextUtils.isEmpty(message)) { textView.setText(message + " Fragment"); } else { textView.setText("Fragment"); } textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (listener != null) { listener.onFragmentClick(); } } }); }}

具体效果如图:

image


七、Fragment懒加载方案

FragmentViewPager结合使用时,ViewPager会预加载下一页的内容,导致浪费用户的流量,所以需要通过懒加载的方式优化。当Fragment的界面显示是,再去加载数据,具体实现如下:

LazyFragment

public abstract class LazyFragment extends Fragment {
protected boolean isVisible; /** * 在这里实现Fragment数据的缓加载. */ @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (getUserVisibleHint()) { isVisible = true; onVisible(); } else { isVisible = false; onInvisible(); } } protected void onVisible() { lazyLoad(); } protected abstract void lazyLoad(); protected void onInvisible() { }}

MyLazyFragment实现

public class MyLazyFragment extends LazyFragment {
private String message; // 标志位,标志已经初始化完成。 private boolean isPrepared; public static MyLazyFragment getInstance(String message) { Bundle bundle = new Bundle(); bundle.putString("message", message); MyLazyFragment firstFragment = new MyLazyFragment(); firstFragment.setArguments(bundle); return firstFragment; } @Override public void onAttach(Context context) { super.onAttach(context); Bundle bundle = getArguments(); if (bundle != null) { message = bundle.getString("message"); } if (message == null) { message = ""; } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_content, container, false); // view.findViewById() 操作获取布局中的View对象 isPrepared = true; lazyLoad(); return view; } @Override protected void lazyLoad() { if (!isPrepared || !isVisible) { return; } //获取数据,填充控件 }}

八、Fragment常见的异常和解决方案

前面讲的内容都是比较基础的知识,关于Fragment常见的异常和解决方案,可以参考下面的博客,总结的很好。


九、DialogFragment创建视图介绍

DialogFragmentFragment的子类,同时具有Dialog的特性,Google官方推荐使用,替代AlertDialog

DialogFragment的使用和Fragment是一样的,这里不做解释。这里讲讲DialogFragment 创建一个视图的2种方式。

  • 通过onCreateDialog()方法,创建Dialog的视图
public class AlertDiaolgFragment extends DialogFragment {
public static void showDialog(FragmentManager manager) { FragmentTransaction transaction = manager.beginTransaction(); transaction.addToBackStack("Alert"); AlertDiaolgFragment diaolgFragment = new AlertDiaolgFragment(); diaolgFragment.show(transaction, "Alert"); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { View view = LayoutInflater.from(getActivity()).inflate(R.layout.dialog, null); return new AlertDialog.Builder(getActivity()) .setTitle("Dialog") .setMessage("今天星期五") .setView(view) .setPositiveButton("OK", null) .setNegativeButton("Cancel", null) .create(); }}
  • 通过onCreateView()方法,直接加载视图,这里的用法就完全是Fragment的用法
public class MyDialogFragment extends DialogFragment {
public static void showDialog(FragmentManager manager) { FragmentTransaction transaction = manager.beginTransaction(); transaction.addToBackStack("My"); AlertDiaolgFragment diaolgFragment = new AlertDiaolgFragment(); diaolgFragment.show(transaction, "My"); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { return LayoutInflater.from(getActivity()).inflate(R.layout.dialog, container,false); }}

十、DialogFragment调用show()方法导致Can not perform this action after onSaveInstanceState异常的解决方案

在使用DialogFragment的时候,偶尔会遇到如下异常,在Activity的生命周期方法走了onSaveInstanceState()方法后,在调用DialogFragmentshow()方法,导致异常:Can not perform this action after onSaveInstanceState

关于Can not perform this action after onSaveInstanceState异常问题,我们的处理方式是:确保是在ActivityFragment的处于onResume()状态调用。在Fragment中有isResume()方法,通过判断该方法,是否显示Fragment。在Activity中,通过在onResume()onPause()设置变量量控制。

以上面的MyDialogFragment为例,如:

在Fragment中,需要显示MyDialogFragment的视图调用if(isResume()){    MyDialogFragment.showDialog(getFragmentManager);}在Activity中,需要显示MyDialogFragment的视图调用private boolean mState;if(mState){     MyDialogFragment.showDialog(getFragmentManager);}@Overrideprotected void onResume() {    super.onResume();    mState = true;}@Overrideprotected void onPause() {    super.onPause();    mState = false;}

转载地址:http://lesvn.baihongyu.com/

你可能感兴趣的文章
#剑指offer Day3 一类 “ 斐波那契 ”问题
查看>>
#剑指offer Day4 一类 “ 双指针 ”问题
查看>>
#剑指offer Day5 # 分享两个题的其他解法
查看>>
缓存淘汰算法的实现与应用介绍(LRU,LFU)
查看>>
JZ15. 反转链表
查看>>
1. 两数之和
查看>>
2. 两数相加
查看>>
JZ1.二维数组的查找
查看>>
String 类
查看>>
什么是接口
查看>>
Java高级篇之进程
查看>>
类加载机制
查看>>
了解jdk1.8版本一些新的特性
查看>>
Java高级篇之网络通讯
查看>>
浅谈篇之线程池
查看>>
Lambda 表达式
查看>>
字符串函数MySQL
查看>>
8个SQL讲解优化
查看>>
MySQL实战续(二)
查看>>
安装Elastic和kibana
查看>>