美文网首页
Android基础组件之Fragment

Android基础组件之Fragment

作者: 小白象码农 | 来源:发表于2018-09-06 10:32 被阅读10次

本篇主要复习Fragment的清单如下:

  • Fragment的生命周期

  • Fragment加载的两种方式

  • Fragment之DialogFragment使用

  • Fragment通信

  • 使用Fragment时的注意事项

一.Fragment的生命周期

a. 官方生命周期图


b.Fragment生命周期方法调用场景

方法 解释
onAttach() Fragment和Activity建立联系时调用(获取Activity传递的值)
onCreateView() Fragment创建View(加载布局)时调用
onActivityCreated() ActivityonCreate()方法执行完毕后调用
onDestoryView() Fragment布局被移除时调用
onDetach() FargmentActivity解除关联时调用

c.Fragment和Activity生命周期对比图


1.创建流程:先执行Activity的生命周期回调,在执行Fragment方法
2.销毁流程:先执行Fragment的生命周期,在执行Acstivity的方法

二.Fragment加载方式

a.静态加载
Fragment的静态添加 :

//BlankFragment.java
public class BlankFragment extends Fragment {

    public BlankFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // 1. 加载布局,第三个参数必须为`false`,否则会加载两次布局并且抛出异常!!
        return inflater.inflate(R.layout.fragment_blank, container, false);
    }
}
//fragment的布局
<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="com.example.a6005001819.androiddeveloper.Fragment.BlankFragment">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/hello_blank_fragment" />

</FrameLayout>

在Activity的布局文件中添加:

//如一般Activity代码-直接省略
如果Fragment使用的是support-v4中的, Activity需要继承自FragmentActivity

Activity的布局

//用fragment标签加载fragment
<?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"
    android:orientation="vertical"
    tools:context="com.example.a6005001819.androiddeveloper.MainActivity">

    <fragment
      android:id="@+id/example_fragment"
        android:name="com.example.a6005001819.androiddeveloper.Fragment.BlankFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

1 如果Fragment属于android.support.v4.app.Fragment包,所用Activity必须继承FragmentActivity
2 如果Fragment属于android.app.Fragment,直接使用Activity即可

b 动态加载

  • Fragment代码不变
  • Activity中进行动态添加
public class MainJavaActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_java);

        //1. 获取FragmentManager
        FragmentManager fragmentManager = getFragmentManager();
        //2. 获取FragmentTransaction
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        //3. 创建Fragment
        BlankFragment blankFragment = new BlankFragment();
        //4. 将Fragment替换到Activity的布局中(Framelayout)
        fragmentTransaction.add(R.id.main_java_activity_container, blankFragment);
        fragmentTransaction.commit();
    }
}
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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="com.example.a6005001819.androiddeveloper.MainJavaActivity">

    <FrameLayout
        android:id="@+id/main_java_activity_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></FrameLayout>

</android.support.constraint.ConstraintLayout>

重复添加

问题:Fragment的动态添加是在onCreate()中,当手机横竖屏切换,会导致多次调用onCreate()最终导致创建多个Fragment
解决办法:在onCreate()检查参数savedInstanceState来确定是第一次运行还是恢复后运行

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main_java);

    if(savedInstanceState == null){
        //1. 获取FragmentManager(support-v4中用`getSupportFragmentManager`)
        FragmentManager fragmentManager = getFragmentManager();
        //2. 获取FragmentTransaction
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        //3. 创建Fragment
        BlankFragment blankFragment = new BlankFragment();
        //4. 将Fragment替换到Activity的布局中(Framelayout)
        fragmentTransaction.add(R.id.main_java_activity_container, blankFragment);
        fragmentTransaction.commit();

        Log.i("feather", "创建新的Fragment");
    }
}

三 DialogFragment 使用

a DialogFragment的作用与优缺点

DialogFragment在Android 3.0提出,用于替代Dialog
优点:旋转屏幕也能保留对话框状态
自定义对话框样式: 继承DialogFragment并重写onCreateView(),该方法返回对话框UI

//自定义DialogFragment
public class CustomDialogFragment extends DialogFragment{

    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        //1. 消除标题
        getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
        //2. 自定义样式
        View root = inflater.inflate(R.layout.fragment_blank, container);
        return root;
    }
}
//使用DialogFragment
CustomDialogFragment dialogFragment = new CustomDialogFragment();
dialogFragment.show(getFragmentManager(), "dialog");

四 Fragment的通信

a EventBus是解决Fragment通信的终极解决方案

1.Fragment通信涉及:Fragment向Activity传递数据、Activity向Fragment传递数据、Fragment之间床底数据

  1. EventBus: 一个Android事件发布/订阅轻量级框架—能够便捷、高效解决Fragment所有通信问题

b Fragment和Activity

  • Fragment调用Activity中的方法

1.getActivity()或者onAttach()中Context转为Activity(不推荐使用getActivity获取,容易空指针)
2.用该Activity对象,调用Activity的对象方法。

  • Activity调用Fragment中的方法

1.Activity中直接用该Fragment对象去调用方法。
2.用过接口回调

  • Activity向Fragment传递数据

1.通过构造函数传递数据(不推荐)
2.通过参数传递数据,在Fragment中onAttach()中getArguments()
3.在Activity中获取Fragment对象,直接调用Fragment的方法,通过参数传递数据

  • Fragment之间的通信

1.需要借助Activity进行数据通信
2.Activity中通过FragmentManager的findFragmentById去获取Fragment

五 使用Fragment时的注意事项

  • Fragment的常见问题,以及如何处理?

1.getActivity()空指针:常见于进行异步操作的时候,此时如果Fragment已经onDetach(),就会遇到。解决办法:在Fragment里面使用一个全局变量mActivity,可能会导致内存泄露。但是比崩溃更好。
2.视图重叠:主要是因为Fragment的onCreate()中没有判断saveInstanceSate == null,导致重复加载了同一个Fragment

  • Fragment的切换方式有多少种?

1.add()、replace()、remove(): 会将Fragment进行移除(就是回收了实例),每次都会新建一个实例。
2.hide()、show()
3.detach()、attach()

  • add和replace的区别

1.replace会将栈中的fragment全部remove,再add进行添加。
2.add是在原有基础上进行添加。

  • Fragment中onCreateView()

1.内部加载布局的inflate()的第三个参数必须是false,否则会导致重复添加,抛出异常

  • Fragment需要传入参数该怎么做?

1.应该通过setArguments(Bundle bundle)方法添加
2.之后通过onAttach()中的getArguments()获得传进来的参数。
3.不建议通过给Fragment添加带参数的构造函数来传参数,这样内存紧张时被系统杀掉会导致无法恢复数据

  • Fragment中获取Activity对象

1.不应该!使用getActivity()获取
2.应该在onAttach()中将Context对象强转为Activity对象

  • 不能在onSaveInstanceState()后调用commit()

1.onSaveInstanceState()在onPause()和onStop()之间调用。
2.onRestoreInstanceState()在onStart()和onResume()之间调用。
避免异常方法:
3.不要把Fragment事务放在异步线程的回调中,比如不要把Fragment事务放在AsyncTask的onPostExecute()—onPostExecute()可能会在onSaveInstanceState()之后执行。
4.无可奈何时使用commitAllowingStateLoss()-一般不推荐。

希望这篇文章对你有帮助~
推荐大神最全面的Fragment解析
YoKey之Fragment全解析系列

相关文章

网友评论

      本文标题:Android基础组件之Fragment

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