Fragment详解

一.Fragment简介

 

   Fragment是Android3.0后引入的一个新的API,它出现的初衷是为了适应大屏幕的平板电脑, 当然现在它仍然是平板APP UI设计的宠儿,而且我们普通手机开发也会加入这个Fragment, 我们可以把他看成一个小型的Activity,又称Activity片段。如果一个很大的界面,我们 就一个布局,写起界面来会有多麻烦,而且如果组件多的话是管理起来也很麻烦。而使用Fragment 我们可以把屏幕划分成几块,然后进行分组,进行一个模块化的管理。从而可以更加方便的在 运行过程中动态地更新Activity的用户界面。另外Fragment并不能单独使用,它需要嵌套在Activity 中使用,尽管它拥有自己的生命周期,但是还是会受到宿主Activity的生命周期的影响,比如Activity 被destory销毁了,它也会跟着销毁。

 

FragmentTransaction事务

   我们通过需要对一个个Fragment进行操作,比如动态添加、替换、隐藏等。这一系列的操作构成一个集合,我们称为事务Transaction。


   FragmentManager中用来处理这些事务的类是FragmentTransaction。在Activity中,通过getSupportFragmentManager()获取到FragmentManager之后,调用beginTransaction()就可以得到一个FragmentTransaction对象。

 

 

 

 

 

二.Fragment生命周期图

 

1.和Activity生命周期对比图

 

 

 

 

 

2.Fragment生命周期图

 

 

 

 

 

 

 

 

 

三.创建一个Fragment

 

将Fragment添加到Activity中,或者是Fragment的使用。有两种方式。静态加载Fragment动态加载Fragment。下面结合代码具体讲解。

 

1.静态加载Fragment

 

代码

Activity代码

package com.wjn.viewlistdemo.activity.fragment;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.wjn.viewlistdemo.R;

public class StaticActivity extends AppCompatActivity {

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

 

Activity布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical">

    <fragment

        android:id="@+id/activity_one_fragment"

        android:name="com.wjn.viewlistdemo.activity.fragment.StaticFragment"


        android:layout_width="match_parent"
        android:layout_height="match_parent"


        tools:layout="@layout/fragment_static">

    </fragment>

</LinearLayout>

说明

   <1> 通过name属性将Fragment引入Activity布局(被引入的Fragment要写全路径)。

   <2> fragment必须指定id,否则报错。

 

Fragment代码

package com.wjn.viewlistdemo.activity.fragment;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.wjn.viewlistdemo.R;
import com.wjn.viewlistdemo.activity.tts.nativetts.NativeTTSActivity;

public class StaticFragment extends Fragment {

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        Log.d("StaticFragment","onAttach方法执行");
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("StaticFragment","onCreate方法执行");
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_static, container, false);
        initView(view);
        Log.d("StaticFragment","onCreateView方法执行");
        return view;
    }

    /**
     * 初始化各种View
     * */

    private void initView(View view){
        TextView textView=view.findViewById(R.id.fragment_static_textview);
        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(getActivity(), NativeTTSActivity.class);
                getActivity().startActivity(intent);
            }
        });
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.d("StaticFragment","onActivityCreated方法执行");
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.d("StaticFragment","onStart方法执行");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d("StaticFragment","onResume方法执行");
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.d("StaticFragment","onPause方法执行");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.d("StaticFragment","onStop方法执行");
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.d("StaticFragment","onDestroyView方法执行");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("StaticFragment","onDestroy方法执行");
    }

    @Override
    public void onDetach() {
        super.onDetach();
        Log.d("StaticFragment","onDetach方法执行");
    }
}

 

Fragment布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/fragment_static_textview"
        android:layout_width="200dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimary"
        android:gravity="center"
        android:layout_centerInParent="true"
        android:text="跳转"
        android:textColor="#ffffff" />


</RelativeLayout>

 

效果

 

刚刚进入

D/StaticFragment: onAttach方法执行

D/StaticFragment: onCreate方法执行

D/StaticFragment: onCreateView方法执行

D/StaticFragment: onActivityCreated方法执行

D/StaticFragment: onStart方法执行

D/StaticFragment: onResume方法执行

 

点击“跳转”按钮跳转到其他页面(此页面被覆盖但没有销毁)

D/StaticFragment: onPause方法执行

D/StaticFragment: onStop方法执行

 

关闭其他页面(此页面又重新回到前台)

D/StaticFragment: onStart方法执行

D/StaticFragment: onResume方法执行

 

退出此页面对应的Activity

D/StaticFragment: onPause方法执行

D/StaticFragment: onStop方法执行

D/StaticFragment: onDestroyView方法执行

D/StaticFragment: onDestroy方法执行

D/StaticFragment: onDetach方法执行

 

 

 

 

2.动态加载Fragment

代码

Activity代码

package com.wjn.viewlistdemo.activity.fragment;

import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.wjn.viewlistdemo.R;

public class DynamicActivity extends AppCompatActivity {

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

        Fragment fragment=new DynamicFragment();
        getSupportFragmentManager().beginTransaction().replace(R.id.activity_dynamic_layout,fragment).commit();

    }
}

 

Activity布局

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activity.fragment.DynamicActivity">

    <RelativeLayout
        android:id="@+id/activity_dynamic_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </RelativeLayout>

</android.support.constraint.ConstraintLayout>

 

Fragment代码

package com.wjn.viewlistdemo.activity.fragment;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.wjn.viewlistdemo.R;
import com.wjn.viewlistdemo.activity.tts.nativetts.NativeTTSActivity;

public class DynamicFragment extends Fragment {

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        Log.d("DynamicFragment", "onAttach方法执行");
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("DynamicFragment", "onCreate方法执行");
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Log.d("DynamicFragment", "onCreateView方法执行");
        View view = inflater.inflate(R.layout.fragment_dynamic, container, false);
        initView(view);
        return view;
    }

    /**
     * 初始化各种View
     * */

    private void initView(View view){
        TextView textView=view.findViewById(R.id.fragment_dynamic_textview);
        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(getActivity(), NativeTTSActivity.class);
                getActivity().startActivity(intent);
            }
        });
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.d("DynamicFragment", "onActivityCreated方法执行");
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.d("DynamicFragment", "onStart方法执行");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d("DynamicFragment", "onResume方法执行");
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.d("DynamicFragment", "onPause方法执行");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.d("DynamicFragment", "onStop方法执行");
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.d("DynamicFragment", "onDestroyView方法执行");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("DynamicFragment", "onDestroy方法执行");
    }

    @Override
    public void onDetach() {
        super.onDetach();
        Log.d("DynamicFragment", "onDetach方法执行");
    }
}

 

Fragment布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/fragment_dynamic_textview"
        android:layout_width="200dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimary"
        android:gravity="center"
        android:layout_centerInParent="true"
        android:text="跳转"
        android:textColor="#ffffff" />


</RelativeLayout>

 

效果

 

刚刚进入

D/DynamicFragment: onAttach方法执行

D/DynamicFragment: onCreate方法执行

D/DynamicFragment: onCreateView方法执行

D/DynamicFragment: onActivityCreated方法执行

D/DynamicFragment: onStart方法执行

D/DynamicFragment: onResume方法执行

 

点击“跳转”按钮跳转到其他页面(此页面被覆盖但没有销毁)

D/DynamicFragment: onPause方法执行

D/DynamicFragment: onStop方法执行

 

关闭其他页面(此页面又重新回到前台)

D/DynamicFragment: onStart方法执行

D/DynamicFragment: onResume方法执行

 

退出此页面对应的Activity

D/DynamicFragment: onPause方法执行

D/DynamicFragment: onStop方法执行

D/DynamicFragment: onDestroyView方法执行

D/DynamicFragment: onDestroy方法执行

D/DynamicFragment: onDetach方法执行

 

 

 

注意

<1> 关于Fragment包

 

<2> 关于FragmentManager

 

 

 

 

 

 

 

四.Fragment常用方法详解

上述中动态添加Fragment的时候,调用了replace方法和commit方法。其实Fragment还有好多方法(尤其在动态加载的时候使用)。下面一一讲解。

 

1.replace(int var1, Fragment var2)

将var1对应的布局替换成var2 Fragment。实际上就是将指定的layout id的Fragment先remove掉,然后再add上去我们指定的var2 Fragment的一种组合操作。

 

 

2.add( int containerViewId, Fragment fragment)

将fragmen添加到我们指定id(containerViewId)的layout中。

 

 

3.hide(Fragment fragment)和show(Fragment fragment)

隐藏或者显示指定的fragment,类似于我们在View中经常使用的setVisibly方法,需要注意的是,这里的hide和show仅仅只是让fragment显示和隐藏,不会对fragment进行销毁,甚至我们在hide的时候fragment的onPause方法都没有被调用。

 

 

4.commit()+commitNow()+commitAllowingStateLoss()+commitNowAllowingStateLoss()

提交事务。区分:

commit()

异步的操作。对应的同步方法为commitNow()。安排当前事务FragmentTransaction进行提交。但是提交后Fragment不会立即创建,而是由主线程异步来创建。也就是说使用commit()之后,你的Fragment不会被立即加入到Activity中。
本次提交,必须在Activity的onSaveInstanceState调用之前提交。否则会抛异常。

 

commitAllowingStateLoss()

和commit类似。但是如果本次是在Activity的onSaveInstanceState调用之后,那么本次提交记录在Activity恢复的时候,可能不被保存。

 

commitNow()

同步的操作。对应的异步方法为commit()。将事务立即提交。所有添加的Fragment会被立即初始化,并开始生命周期。所有被移除的Fragment将会被立即移除。调用这个方法,相当于调用commit,然后调用FragmentManager的executePendingTransactions()。

 

commitNowAllowingStateLoss()

和commitNow类似。但是如果在在Activity的onSaveInstanceState调用之后,那么本次提交记录在Activity恢复的时候,可能不被保存。

 

每个FragmentTransaction只能提交commit一次。包括commit、commitNow、commitAllowingStateLoss、commitNowAllowingStateLoss。提交完一次之后,再commit就会抛出异常。也就是说不要每进行一个操作就commit一次,应该把多个操作都在FragmentTransact。

 

 

5.remove(Fragment fragment)

会将fragment移除,如果被移除的Fragment没有添加到回退栈,该Fragment会同时被销毁。

 

 

6.detach( Fragment fragment)

会将view从UI中移除,和remove()不同,此时fragment并没有与Activity断绝关系,所以生命周期的onDestroy方法和onDetach方法并没有被调用。

 

 

7.attach(Fragment fragment)

重建view视图,附加到UI上并显示,如果调用完detach方法后再来调用该方法的话不会去走onAttach和onCreate方法。

 

 

下面通过代码一一讲解(点击TextView切换两个Fragment)

OneFragment

package com.example.test;

import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class OneFragment extends Fragment {

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        Log.d("TAG", "OneFragment的onAttach方法执行");
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("TAG", "OneFragment的onCreate方法执行");
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Log.d("TAG", "OneFragment的onCreateView方法执行");
        View view = inflater.inflate(R.layout.fragment_one, container, false);
        initView(view);
        return view;
    }

    /**
     * 初始化各种View
     */

    private void initView(View view) {
        TextView textView = view.findViewById(R.id.fragment_one_textview);
        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("TAG", "OneFragment TextView点击");
            }
        });
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.d("TAG", "OneFragment的onActivityCreated方法执行");
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.d("TAG", "OneFragment的onStart方法执行");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d("TAG", "OneFragment的onResume方法执行");
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.d("TAG", "OneFragment的onPause方法执行");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.d("TAG", "OneFragment的onStop方法执行");
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.d("TAG", "OneFragment的onDestroyView方法执行");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("TAG", "OneFragment的onDestroy方法执行");
    }

    @Override
    public void onDetach() {
        super.onDetach();
        Log.d("TAG", "OneFragment的onDetach方法执行");
    }

}

 

TwoFragment

package com.example.test;

import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class TwoFragment extends Fragment {

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        Log.d("TAG", "TwoFragment的onAttach方法执行");
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("TAG", "TwoFragment的onCreate方法执行");
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Log.d("TAG", "TwoFragment的onCreateView方法执行");
        View view = inflater.inflate(R.layout.fragment_two, container, false);
        initView(view);
        return view;
    }

    /**
     * 初始化各种View
     */

    private void initView(View view) {
        TextView textView = view.findViewById(R.id.fragment_two_textview);
        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("TAG", "TwoFragment TextView点击");
            }
        });
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.d("TAG", "TwoFragment的onActivityCreated方法执行");
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.d("TAG", "TwoFragment的onStart方法执行");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d("TAG", "TwoFragment的onResume方法执行");
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.d("TAG", "TwoFragment的onPause方法执行");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.d("TAG", "TwoFragment的onStop方法执行");
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.d("TAG", "TwoFragment的onDestroyView方法执行");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("TAG", "TwoFragment的onDestroy方法执行");
    }

    @Override
    public void onDetach() {
        super.onDetach();
        Log.d("TAG", "TwoFragment的onDetach方法执行");
    }

}

 

1.replace方法 添加

package com.example.test;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;

import android.os.Bundle;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private TextView oneTextView;
    private TextView twoTextView;
    private OneFragment oneFragment;
    private TwoFragment twoFragment;
    private Fragment currentFragment;
    private FragmentManager fm;
    private FragmentTransaction ft;

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

    /**
     * 初始化各种View
     */

    private void initView() {
        oneFragment = new OneFragment();
        fm = getSupportFragmentManager();
        ft = fm.beginTransaction();
        ft.replace(R.id.activity_main_layout, oneFragment).commit();
        currentFragment = oneFragment;

        oneTextView = findViewById(R.id.activity_main_onetextview);
        oneTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (null != currentFragment && currentFragment != oneFragment) {

                    ft = fm.beginTransaction();

                    if (null == oneFragment) {
                        oneFragment = new OneFragment();
                    }

                    currentFragment = oneFragment;

                    ft.replace(R.id.activity_main_layout, oneFragment).commit();
                }

            }
        });


        twoTextView = findViewById(R.id.activity_main_twotextview);
        twoTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (null != currentFragment && currentFragment != twoFragment) {

                    ft = fm.beginTransaction();

                    if (null == twoFragment) {
                        twoFragment = new TwoFragment();
                    }

                    currentFragment = twoFragment;

                    ft.replace(R.id.activity_main_layout, twoFragment).commit();
                }
            }
        });

    }

}

注意:每一个实例化后的 FragmentTransaction 的事物只能被提交一次,我开始时是定义了一个全局的  FragmentTransaction,然后就只在 onCreate() 方法中实例化了一次,但是我设置点击事件切换 fragment 时,会导致二次 commit,所以会报错。

 

结果(默认One,切换到Two,再切换到One)

D/TAG: OneFragment的onAttach方法执行

D/TAG: OneFragment的onCreate方法执行

D/TAG: OneFragment的onCreateView方法执行

D/TAG: OneFragment的onActivityCreated方法执行

D/TAG: OneFragment的onStart方法执行

D/TAG: OneFragment的onResume方法执行


*********************************************


D/TAG: TwoFragment的onAttach方法执行

D/TAG: TwoFragment的onCreate方法执行

D/TAG: OneFragment的onPause方法执行

D/TAG: OneFragment的onStop方法执行

D/TAG: OneFragment的onDestroyView方法执行

D/TAG: OneFragment的onDestroy方法执行

D/TAG: OneFragment的onDetach方法执行

D/TAG: TwoFragment的onCreateView方法执行

D/TAG: TwoFragment的onActivityCreated方法执行

D/TAG: TwoFragment的onStart方法执行

D/TAG: TwoFragment的onResume方法执行


****************************************************


D/TAG: OneFragment的onAttach方法执行

D/TAG: OneFragment的onCreate方法执行

D/TAG: TwoFragment的onPause方法执行

D/TAG: TwoFragment的onStop方法执行

D/TAG: TwoFragment的onDestroyView方法执行

D/TAG: TwoFragment的onDestroy方法执行

D/TAG: TwoFragment的onDetach方法执行

D/TAG: OneFragment的onCreateView方法执行

D/TAG: OneFragment的onActivityCreated方法执行

D/TAG: OneFragment的onStart方法执行

D/TAG: OneFragment的onResume方法执行

可知,replace方式添加Fragment,是要销毁前一个Fragment,然后添加后一个。

 

 

 

2.add+hide+show方法 添加

package com.example.test;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;

import android.os.Bundle;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private TextView oneTextView;
    private TextView twoTextView;
    private OneFragment oneFragment;
    private TwoFragment twoFragment;
    private Fragment currentFragment;
    private FragmentManager fm;
    private FragmentTransaction ft;

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

    /**
     * 初始化各种View
     */

    private void initView() {
        oneFragment = new OneFragment();
        fm = getSupportFragmentManager();
        ft = fm.beginTransaction();
        ft.add(R.id.activity_main_layout, oneFragment).commit();
        currentFragment = oneFragment;

        oneTextView = findViewById(R.id.activity_main_onetextview);
        oneTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (null != currentFragment && currentFragment != oneFragment) {


                    if (null == oneFragment) {
                        oneFragment = new OneFragment();
                    }


                    jumpFragment(currentFragment,oneFragment);

                }

            }
        });


        twoTextView = findViewById(R.id.activity_main_twotextview);
        twoTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (null != currentFragment && currentFragment != twoFragment) {


                    if (null == twoFragment) {
                        twoFragment = new TwoFragment();
                    }

                    jumpFragment(currentFragment,twoFragment);

                }
            }
        });

    }

    /**
     * Fragment跳转
     */

    private void jumpFragment(Fragment from, Fragment to) {
        if (null == from || null == to) {
            return;
        }

        ft = fm.beginTransaction();

        if (!to.isAdded()) {//目标Fragment没有添加过 添加
            ft.hide(from).add(R.id.activity_main_layout, to).commit();
        } else {//目标Fragment没有添加过 显示
            ft.hide(from).show(to).commit();
        }

        currentFragment = to;
    }

}

 

结果(默认One,切换到Two,再切换到One。 来回切换)

D/TAG: OneFragment的onAttach方法执行

D/TAG: OneFragment的onCreate方法执行

D/TAG: OneFragment的onCreateView方法执行

D/TAG: OneFragment的onActivityCreated方法执行

D/TAG: OneFragment的onStart方法执行

D/TAG: OneFragment的onResume方法执行


*********************************************************


D/TAG: TwoFragment的onAttach方法执行

D/TAG: TwoFragment的onCreate方法执行

D/TAG: TwoFragment的onCreateView方法执行

D/TAG: TwoFragment的onActivityCreated方法执行

D/TAG: TwoFragment的onStart方法执行

D/TAG: TwoFragment的onResume方法执行


************************************************************

无...




可知,hide和show仅仅只是让fragment显示和隐藏,不会对fragment进行销毁,甚至我们在hide的时候fragment的onPause方法都没有被调用。

 

 

 

 

 

 

 

五.Fragment与Activity的通信

 

1.Activit传递数据给Fragment

Activity传递数据给Fragment有很多中方式,下面介绍两种常用的方式。

 

<1> setArguments(bundle)getArguments()方法

在Activity中创建Bundle数据包,调用Fragment实例的setArguments(bundle) 从而将Bundle数据包传给Fragment,然后Fragment中调用getArguments获得 Bundle对象,然后进行解析就可以了。Bundle对象要判空

 

Activity 传值

package com.wjn.viewlistdemo.activity.fragment;

import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.wjn.viewlistdemo.R;

public class DynamicActivity extends AppCompatActivity {

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

        Fragment fragment = new DynamicFragment();
        Bundle bundle = new Bundle();
        bundle.putString("name", "张三");
        bundle.putInt("age", 29);
        fragment.setArguments(bundle);
        getSupportFragmentManager().beginTransaction().replace(R.id.activity_dynamic_layout, fragment).commit();
    }
}

 

Fragment 接收

package com.wjn.viewlistdemo.activity.fragment;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.wjn.viewlistdemo.R;

public class DynamicFragment extends Fragment {

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_dynamic, container, false);
        initView(view);
        return view;
    }

    /**
     * 初始化各种View
     */

    private void initView(View view) {
        Bundle bundle = getArguments();
        if (null == bundle) {
            Log.d("DynamicFragment", "接收Activity传值bundle为空即没有传值要判断一下");
            return;
        }
        String name = bundle.getString("name", "");
        int age = bundle.getInt("age");
        Log.d("DynamicFragment", "接收Activity传值name----:" + name);
        Log.d("DynamicFragment", "接收Activity传值age----:" + age);
    }
}

 

结果

D/DynamicFragment: 接收Activity传值name----:张三

D/DynamicFragment: 接收Activity传值age----:29

 

注意

要是Activity没有传值,那么接收的时候bundle就会为空。所以判断一下最好。

 

 

 

<2> Activity中调用Fragment的方法

Activity 传值

package com.wjn.viewlistdemo.activity.fragment;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

import com.wjn.viewlistdemo.R;

public class DynamicActivity extends AppCompatActivity {

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

        DynamicFragment fragment = new DynamicFragment();
        fragment.updateFragment("张三",30);
        getSupportFragmentManager().beginTransaction().replace(R.id.activity_dynamic_layout, fragment).commit();
    }
}

 

Fragment 接收

package com.wjn.viewlistdemo.activity.fragment;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.wjn.viewlistdemo.R;

public class DynamicFragment extends Fragment {

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_dynamic, container, false);
        return view;
    }

    /**
     * Activity更新Fragment
     */

    public void updateFragment(String name, int age) {
        Log.d("DynamicFragment", "接收Activity传值name----:" + name);
        Log.d("DynamicFragment", "接收Activity传值age----:" + age);
    }

}

 

结果

D/DynamicFragment: 接收Activity传值name----:张三

D/DynamicFragment: 接收Activity传值age----:30

 

注意

由于在Activity中创建Fragment对象时要调用XXXFragment中的某个方法,所以声明的对象应该是XXXFragment,而不是Fragment。这里具体的是

DynamicFragment fragment = new DynamicFragment();

 

 

 

 

 

2.Fragment传递数据给Activity

 

同样Fragment传递数据给Activity也有有很多中方式,下面介绍两种常用的方式。

 

<1> 接口回调

Fragment 传值

package com.wjn.viewlistdemo.activity.fragment;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.wjn.viewlistdemo.R;

public class DynamicFragment extends Fragment {

    private FragmentToActivityCallBack mCallBack;

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Log.d("DynamicFragment", "onCreateView方法执行");
        View view = inflater.inflate(R.layout.fragment_dynamic, container, false);
        initView(view);
        return view;
    }

    /**
     * 初始化各种View
     */

    private void initView(View view) {
        TextView textView = view.findViewById(R.id.fragment_dynamic_textview);
        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (null != mCallBack) {
                    mCallBack.updateActivityString("张三");
                    mCallBack.updateActivityInt(30);
                }
            }
        });
    }

    /**
     * 设置监听事件
     */

    public void setFragmentToActivityCallBack(FragmentToActivityCallBack callBack) {
        mCallBack = callBack;
    }

}

 

package com.wjn.viewlistdemo.activity.fragment;

public interface FragmentToActivityCallBack {

    void updateActivityString(String name);

    void updateActivityInt(int age);

}

 

Activity 接收

package com.wjn.viewlistdemo.activity.fragment;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import com.wjn.viewlistdemo.R;

public class DynamicActivity extends AppCompatActivity implements FragmentToActivityCallBack {


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

        DynamicFragment fragment = new DynamicFragment();
        fragment.setFragmentToActivityCallBack(this);
        getSupportFragmentManager().beginTransaction().replace(R.id.activity_dynamic_layout, fragment).commit();
    }

    @Override
    public void updateActivityString(String name) {
        Log.d("DynamicActivity", "Fragment传值给Activity name----:" + name);
    }

    @Override
    public void updateActivityInt(int age) {
        Log.d("DynamicActivity", "Fragment传值给Activity age----:" + age);
    }
}

 

结果

D/DynamicActivity: Fragment传值给Activity name----:张三

D/DynamicActivity: Fragment传值给Activity age----:30

 

 

 

 

<2> Fragment中调用Activity的方法

Fragment 传值

package com.wjn.viewlistdemo.activity.fragment;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.wjn.viewlistdemo.R;

public class DynamicFragment extends Fragment {

    private DynamicActivity dynamicActivity;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (null == context) {
            return;
        }
        dynamicActivity = (DynamicActivity) context;
    }

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Log.d("DynamicFragment", "onCreateView方法执行");
        View view = inflater.inflate(R.layout.fragment_dynamic, container, false);
        initView(view);
        return view;
    }

    /**
     * 初始化各种View
     */

    private void initView(View view) {
        TextView textView = view.findViewById(R.id.fragment_dynamic_textview);
        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (null != dynamicActivity) {
                    dynamicActivity.updateActivityString("张三");
                    dynamicActivity.updateActivityInt(31);
                }
            }
        });
    }

}

 

Activity 接收

package com.wjn.viewlistdemo.activity.fragment;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import com.wjn.viewlistdemo.R;

public class DynamicActivity extends AppCompatActivity {

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

        DynamicFragment fragment = new DynamicFragment();
        getSupportFragmentManager().beginTransaction().replace(R.id.activity_dynamic_layout, fragment).commit();
    }

    public void updateActivityString(String name) {
        Log.d("DynamicActivity", "Fragment传值给Activity name----:" + name);
    }

    public void updateActivityInt(int age) {
        Log.d("DynamicActivity", "Fragment传值给Activity age----:" + age);
    }
}

 

结果

D/DynamicActivity: Fragment传值给Activity name----:张三

D/DynamicActivity: Fragment传值给Activity age----:31

 

说明

在Fragment中的onAttach生命周期方法中通过传递的Context对象,强转成对应的动态加载的Activity对象。就可以拿着Activity对象调用Activity中的方法了。但是这种方式有不妥的地方,比如多个Activity都动态加载该Fragment,在onAttach生命周期方法中就不好强转那个Activity对象了。

 

 

 

 

 

 

 

六.Fragment回退栈

 

 简介

我们知道Activity有任务栈,通过startActivity入栈,点击返回按钮将Activity出栈。Fragment也有类似的栈,称为回退栈(Back Stack)。

回退栈是由FragmentManager管理的。默认情况下,Fragment事务是不会加入回退栈的,如果想将Fragment事务加入回退栈,则可以加入addToBackStack("")。如果没有加入回退栈,则用户点击返回按钮会直接将Activity出栈;如果加入了回退栈,则用户点击返回按钮会回滚Fragment事务。

 

在使用add方法动态添加Fragment时,addToBackStack("fname")是可选的。FragmentManager拥有回退栈(BackStack),类似于Activity的任务栈,如果添加了该语句,就把该事务加入回退栈,当用户点击返回按钮,会回退该事务(回退指的是如果事务是add(frag1),那么回退操作就是remove(frag1));如果没添加该语句,用户点击返回按钮会直接销毁Activity。

 

 

 

 

 

 

 

 

七.项目使用

 

详见: Fragment+ViewPager实现导航滑动切换页面

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值