Android实战开发中Fragment你所应该知道的一切

版权声明:本文出自门心叼龙的博客,转载请注明出处。 https://blog.csdn.net/geduo_83/article/details/86559417

本文为自己多年来在Android实战开发过程中总结归纳的一些常见问题,现在分享出来希望对初学者有所帮助。

本文出自门心叼龙的博客,转载请注明出处: https://blog.csdn.net/geduo_83/article/details/86559417

 目录

1. 请简述Fragment的意义?

2. 将一个Fragment添加到Activity布局的方式有几种?

3. 简述Fragment生命周期,常用的回调方法有几个?各个回调方法的意义?

4.怎么为Fragment绑定UI布局?

5.怎么去管理Fragment?

6.执行Fragment的事务,事务有什么特点?

7.为Activity创建Fragment的事件回调?

8.在Fragment中创建菜单直接复写onCreateOptionMenu方法可以吗?

9.如何实现多个Fragment之间的灵活切换?

10. Activity和Fragment 的 onActivityForResult 回调?

11. Fragment的View重复添加导致的崩溃问题?

12. Fragment的getActivity方法返回null的原因:

13.ViewPager中Fragment的缓存


1. 请简述Fragment的意义?

  • 1.1 Fragment是Activity界面的一部分,Fragment是依附于Activity之上的;
  • 1.2 Activity是Fragment的基础,Fragment是Activity的延续和发展
  • 1.3 一个Activity可以有多个Fragment,一个Fragment也可以被多个Activity重复使用;       
  • 1.4 一个Fragment除了Activity处于onResume状态下,他可以自己灵活的控制自己的生命周期,其他状态下,其生命周期都是由Activity所决定的; 
  •  1.5 Fragment的出现增强了UI界面布局的灵活性,可以实现动态的改变UI布局;

2. 将一个Fragment添加到Activity布局的方式有几种?

  • 2.1 通过fragment标签加入(静态加入)
  • 2.2 通过代码动态的加入(动态加入)

3. 简述Fragment生命周期,常用的回调方法有几个?各个回调方法的意义?

  • onActtch:初始化Fragment 事件回调接口
  • onCreate:初始化参数
  • onCreateView:为Fragment绑定布局
  • onViewCreated:进行控件实例化操作
  • onPause:在用户离开Fragment是所进行的一些数据持久化操作

当Activity的onCreate方法被回调时会导致fragment方法的onAttach()、onCreate()、onCreateView()、onActivityCreate() 被连续回调

4.怎么为Fragment绑定UI布局?

复写onCreateView方法
inflate方法有三个参数

  • 参数1:需要绑定的Layout的资源Id
  • 参数2:绑定Layout布局的父视图
  • 参数3:是否将参数1的Layout资源依附于参数2的ViewGroup之上

注意了:不管参数3是否为true都依附,系统默认已经将Layout插入至ViewGroup上如果为true,将添加一层冗余的视图

5.怎么去管理Fragment?

  • 通过getFragmentManager()方法获取FragmentManager实例
  • 调用findFragmentById()或者findFragmentByTag()方法来获取一个Fragment
  • 调用popBackStack方法将Fragment从后退站中弹出
  • 调用addOnBackChangedListener()方法注册监听器,用于监听后退站的变化

6.执行Fragment的事务,事务有什么特点?

每个事务都表示执行一组变化,这些变化包括add()、remove()、replace()、addToBackStack()、setCustomAnimations、setTransition事务要生效必须调用commit,commit并不会立即执行,只能等待UI主线程空闲时才能执行也可以调用executePendingTransactions立即生效提交事务,commit在调用时机是Activity状态保存之前进行,也就是说如果在离开Activity是进行提交事务的操作,系统就会抛出异常

7.为Activity创建Fragment的事件回调?

  • 7.1Fragment创建一个接口
  • 7.2Activity实现这个接口
  • 7.3在onActtch方法初始化接口

8.在Fragment中创建菜单直接复写onCreateOptionMenu方法可以吗?

不行,必须在onCreate方法是调用setHasOptionsMenu方法才行onOptionItemSelected进行选择回调

9.如何实现多个Fragment之间的灵活切换?

public void switchContent(Fragment from, Fragment to) {
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    if (!to.isAdded()) {
        transaction.hide(from).add(R.id.frame_content, to).commit();
    } else {
        transaction.hide(from).show(to).commit();
   }
}

10. Activity和Fragment 的 onActivityForResult 回调?

  • 10.1 当在Fragment里面调用startActivityForResult的时候 Activity和Fragment里面的onActivityForResult都会回调,只不过Fragment里面回调的requestCode是正确的
  • 10.2 当在Fragment里面调用getActivity().startActivityForResult的时候,就会回调Activity里面的onActivityForResult
  • 10.3 当Fragment存在多层嵌套的情况,内层的Fragment调用startActivityForResult的时候,onActivityForResult方法不回调,此时需要
  • 10.3.1 创建一个BaseActivity复写它的onActivityResult方法
public class BaseFragmentActiviy extends FragmentActivity {
 private static final String TAG = "BaseActivity";

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  FragmentManager fm = getSupportFragmentManager();
  int index = requestCode >> 16;
  if (index != 0) {
   index--;
   if (fm.getFragments() == null || index < 0
     || index >= fm.getFragments().size()) {
    Log.w(TAG, "Activity result fragment index out of range: 0x"
      + Integer.toHexString(requestCode));
    return;
   }
   Fragment frag = fm.getFragments().get(index);
   if (frag == null) {
    Log.w(TAG, "Activity result no fragment exists for index: 0x"
      + Integer.toHexString(requestCode));
   } else {
    handleResult(frag, requestCode, resultCode, data);
   }
   return;
  }

 }

 /**
  * 递归调用,对所有子Fragement生效
  * 
  * @param frag
  * @param requestCode
  * @param resultCode
  * @param data
  */
 private void handleResult(Fragment frag, int requestCode, int resultCode,
   Intent data) {
  frag.onActivityResult(requestCode & 0xffff, resultCode, data);
  List<Fragment> frags = frag.getChildFragmentManager().getFragments();
  if (frags != null) {
   for (Fragment f : frags) {
    if (f != null)
     handleResult(f, requestCode, resultCode, data);
   }
  }
 }
  • 10.3.2 启动Activity的时候一定要用根Fragment
/**
  * 得到根Fragment
  * 
  * @return
  */
 private Fragment getRootFragment() {
  Fragment fragment = getParentFragment();
  while (fragment.getParentFragment() != null) {
   fragment = fragment.getParentFragment();
  }
  return fragment;

 }

 /**
  * 启动Activity
  */
 private void onClickTextViewRemindAdvancetime() {
  Intent intent = new Intent();
  intent.setClass(getActivity(), YourActivity.class);
  intent.putExtra("TAG","TEST"); 
  getRootFragment().startActivityForResult(intent, 1001);
 }

11. Fragment的View重复添加导致的崩溃问题?

如果把该view添加到父view那么也会引起重复添加而导致崩溃

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
    Bundle savedInstanceState) {
  if (view == null) {
    view = inflater.inflate(R.layout.dd_fragment_year, container, false);
}
ViewGroup viewGroup = (ViewGroup) view.getParent();  
if (viewGroup != null){
viewGroup.removeView(view);
} 
  return view;
}

12. Fragment的getActivity方法返回null的原因:

如果系统内存不足、或者切换横竖屏、或者app长时间在后台运行,Activity都可能会被系统回收,但是Fragment并不会随着Activity的回收而被回收,从而导致Fragment丢失对应的Activity。这里,假设我们继承于FragmentActivity的类为MainActivity,其中用到的Fragment为FragmentA。
app发生的变化为:某种原因系统回收MainActivity——FragmentA被保存状态未被回收——再次点击app进入——首先加载的是未被回收的FragmentA的页面——由于MainActivity被回收,系统会重启MainActivity,FragmentA也会被再次加载——页面出现混乱,因为一层未回收的FragmentA覆盖在其上面——(假如FragmentA使用到了getActivity()方法)会报NullPointerException:

  • 方案1:在使用Fragment的Activity中重写onSaveInstanceState方法,将super.onSaveInstanceState(outState)注释掉,让其不再保存Fragment的状态,达到其随着MainActivity一起被回收的效果。
  • 方案2:在再次启动Activity的时候,在onCreate方法中将之前保存过的fragment状态清除,代码示例如下:
if(savedInstanceState!= null){
    String FRAGMENTS_TAG = "android:support:fragments"; 
    savedInstanceState.remove(FRAGMENTS_TAG);
}
  • 方案3:避免使用getActivity方法得到activity,如果确实需要使用上下文,可以写一个类MyApplication继承Application,并且写一个方法getContext(),返回一个Context 对象。代码示例如下:
public class MyApplication extends Application {
    private static Context context;
   @Override
    public void onCreate() {
        super.onCreate();
         context = this;
}
    public static Context getContext() {
        return context;
     }
}

13.ViewPager中Fragment的缓存

当Fragment在Activity中被取消挂载再次挂载的时候Fragment各个生命周期都会重新执行

public class FragmentFound extends Fragment {
    private View view;
    @Override
    public View onCreateView(LayoutInflater inflater,
            @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if(view == null){
            view = inflater.inflate(R.layout.fragment_found, null);
        }
        ViewGroup parentView = (ViewGroup)view.getParent();
        if(parentView != null)
            parentView.removeView(view);
        return view;
    }
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if(isVisibleToUser){
        //刷新操作
    }
}


 

猜你喜欢

转载自blog.csdn.net/geduo_83/article/details/86559417