Android UI组件:Fragment的基本使用

Android UI组件:Fragment的基本使用

概览

主要探讨关于Fragment的基本使用,包括简单的原理以及创建、修改、删除等操作。

在本篇文章中,你将了解到:

  • 1.什么是Fragment。
  • 2.Fragment的生命周期。
  • 3.Fragment的基本使用。
  • 4.Fragment于Activity进行通信
  • 5.理解Fragment和Activity的关系以及分工
  • 6.如何正确的显示、隐藏Fragment

什么是Fragment?

​ 由于Android是一款开源的系统,在国内外不同的厂商研发出了很多不同的机型,甚至将Android应用到了平板中,但是这意味着不同厂商出产的手机、平板的屏幕大小不一,例如,组件排版安装5.0寸手机制作的程序,如果在4.7寸的手机上,视觉效果体验虽说会降低,但也不至于不可接受。但是如果放到6.0寸的手机,乃至平板上,用户的视觉体验会大幅度降低。
这就导致了Android研发的工作中有比较大的比重的分辨率匹配,而Fragment则是用来解决这一问题的。
这是因为,Fragment是依赖于Activity的,在Activity的布局中创建一个FrameLayout组件,就可以在上面根据不同的需要显示很多个Fragment(当然不能同时显示)。并且Fragment有自己的生命周期、自己的布局文件、独立的事件处理,极端的说,你甚至可以把一个Fragment当做一个Activity来使用。

Fragment的生命周期

​ 前面说过,Fragment是依赖于Activity的,即必须先创建Activity,再创建Fragment,并且Fragment的生命周期细节上同Activity所有不同,但仍是可以对应参考的。先来看一下Google官方给出的Fragment与Activity生命周期对照表:

我们现在来简单解释一下Fragment多出来的生命周期:

  • ** onAttach():**

当Fragment与Activity发生关联时调用该方法。

  • onCreateView():

在Fragment中初始化Layout、初始化组件时使用。

  • onActivityCreated():

当Activity的onCreate()返回时调用。

  • onDestoryView():

与onCreateView想对应,当该Fragment的视图被移除时调用。

  • onDetach():

与onAttach相对应,当Fragment与Activity关联被取消时调用。

另外,值得注意的是,除了onCreateView()外,如果你重写了其他方法,则必须调用spue使父类来实现该方法。

准备工作:
本案例中计划使用动态添加Fragment的方式,来分别在同一个FrameLayout组件中分别显示两个不同的Fragment,并且完成替换、删除、在Fragment中修改Activity的内容,以及在Activity中修改Fragment的内容等操作。
首先来看一下效果图:

接着开始进行一些初始化等准备工作,代码如下:
以下代码在activity_main中写入:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:layout_gravity="center_vertical"
        android:text="这里是MainActivity"
        android:textSize="18sp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:orientation="horizontal">

        <Button
            android:id="@+id/ButtonShowFragmentNow"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="显示FragmentNow"
            android:textAllCaps="false" />

        <Button
            android:id="@+id/ButtonShowFragmentTwo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="显示FragmentTwo"
            android:textAllCaps="false" />
    </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:orientation="horizontal">

        <Button
            android:id="@+id/ButtonAmendFragmentTwo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="修改FragmentTwo"
            android:textAllCaps="false" />

        <Button
            android:id="@+id/ButtonReplaceFragmentNow"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="替换" />

        <Button
            android:id="@+id/ButtonDeleteFragmentNow"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="删除FragmentNow"
            android:textAllCaps="false" />
    </LinearLayout>

    <TextView
        android:id="@+id/TextView"
        android:layout_width="match_parent"
        android:layout_height="20dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="5dp"
        android:text="这就是用来被Fragment修改的"
        android:textAllCaps="false"
        android:textSize="18sp" />

    <FrameLayout
        android:id="@+id/FrameLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#D02090" />

</LinearLayout>

值得注意的是,在FrameLayout中添加了背景颜色,如果没有显示Fragment,则显示背景颜色,如果添加了Fragment,则显示Fragment布局文件中定义的颜色。

以下代码在fragment_now中写入:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#9aff9a">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/ButtonFragmentNow"
        android:text="修改Activity"
        android:textAllCaps="false"
        android:layout_gravity="center"/>

</LinearLayout>

以下代码在fragment_two中写入:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#d1eeee"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/TextVIewFragmentTwo"
        android:text="注定被修改"
        android:layout_gravity="center"
        android:textSize="30sp"/>

</LinearLayout>

开始创建Fragment:

在上面的准备工作中,创建了一个FrameLayout组件,而Fragment就会显示在该组件中。另外创建了两个布局文件,这两个布局文件就分别对应两个不同的Fragment。以下首先来看代码思路:

1.首先定义FragmentNow以及FragmentTwo。。
2.接着初始化所需的组件,并设置Button的监听器
3.通过完整的代码显示FragmentNow。
4.通过简略的代码显示fragmentTwo。
5.设置Fragment直接的自由替换。
6.一些其他的应用说明。

以下代码分别在FragmentNow/Two中写入:

/* 代码执行1:
* 1.在创建Fragment时,需要继承自v4.app.Fragment中的Fragment。
* 2.然后创建View对象,用户获取Fragment所需的Layout。
* 3.onCreateView是用于初始化Fragment的视图。
* 4.Amend()用于在Activity中调用该方法,来修改Fragment中的内容。*/
public class FragmentTwo extends Fragment {
    private View mView;
    private TextView mTextView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mView = inflater.inflate(R.layout.fragment_two, null);
        return mView;
    }

    public void Amend(){
        mTextView = (TextView) mView.findViewById(R.id.TextVIewFragmentTwo);
        mTextView.setText("这是FragmentTwo中已经被修改了的值");
    }
}
public class FragmentNow extends Fragment {
    private View mView;
    private Button mButton;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mView = inflater.inflate(R.layout.fragment_now, null);
        mButton = (Button) mView.findViewById(R.id.ButtonFragmentNow);

        return mView;
    }

    /* 代码执行1:
    * 1.1.由于初始化视图必须在onCreateView()中完成,如果向Activity一样在onCreate()中调用Button是不可以的。
    * 1.2.这是因为onCreate()在onCreateView()之前就被调用,如果此时在onCreate()中调用Button,会显示空指针。
    * */
    @Override
    public void onStart() {
        super.onStart();
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MainActivity mainActivity = (MainActivity) getActivity();
                mainActivity.Amend();
            }
        });
    }
}

以下代码在MainActivity中写入:

/* 代码执行2:
    * 1.首先将两个Fragment类创建为对象。用于通过该对象来配合FrameLayout显示fragment。
    * 2.然后获得各个Button的ID。
    * 3.定义一个boolean类型的变量,用于替换时的循环。
    * 4.注意别忘了在onCreate()中调用init()。*/
private void init() {
    mFragmentNow = new FragmentNow();
    mFragmentTwo = new FragmentTwo();
    mButtonShowFragmentNow = (Button) findViewById(R.id.ButtonShowFragmentNow);
    mButtonShowFragmentTwo = (Button) findViewById(R.id.ButtonShowFragmentTwo);
    mButtonAmendFragmentTwo = (Button) findViewById(R.id.ButtonAmendFragmentTwo);
    mButtonReplaceFragmentNow = (Button) findViewById(R.id.ButtonReplaceFragmentNow);
    mButtonDeleteFragmentNow = (Button) findViewById(R.id.ButtonDeleteFragmentNow);
    mBoolean = true;
}

以下代码在MainActivity的onCreate()中写入:

mButtonShowFragmentNow.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        /* 代码执行3:
                * 1.1.首先通过Fragment管理器创建一个Fragment对象,
                * 1.2.通过getSupportFragmentManager来返回同Activity进行关联并交互的Fragment对象。
                * 2.再将已经创建好的Fragment放置到Fragment事务队列中。等待Activity的处理。
                * 3.告知该Fragment事务它的显示位置(在哪个组件上显示),而Fragment所需的逻辑代码在哪个类中(通过对象引用)。
                * 4.这时将Fragment正式提交到Fragment队列中,使Activity进行处理。*/
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.FrameLayout, mFragmentNow);
        fragmentTransaction.commit();
    }
});

以下代码在MainActivity的onCreate()中写入:

mButtonShowFragmentTwo.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        /* 代码执行4:
                * 1.使用精简的方式创建Fragment。并且不使用.add,因为使用.add创建当用户连续点击后,程序将结束运行。
                * */
        getSupportFragmentManager().beginTransaction()
            .replace(R.id.FrameLayout, mFragmentTwo).commit();
    }
});

以下代码在MainActivity的onCreate()中写入:

mButtonReplaceFragmentNow.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        /* 代码执行5:
                * 1.替换Activity。由于只有一个Fragment显示位置,所以只能同时显示一个。
                * 2.每次替换完成后,则修改mBoolean的值,防止陷入死循环。
                * 3.但以上方式会存在一点瑕疵:当当前显示的是mFragment1(默认为真,第一次替换mFragment1)时,第一次点击将(无效果),需要点击两次,反之同理。
                * */
        if (mBoolean) {
            getSupportFragmentManager().beginTransaction()
                .replace(R.id.FrameLayout, mFragmentNow).commit();
            mBoolean = false;
        } else {
            getSupportFragmentManager().beginTransaction()
                .replace(R.id.FrameLayout, mFragmentTwo).commit();
            mBoolean = true;
        }
    }
});

以下代码在MainActivity的onCreate()中写入:

mButtonAmendFragmentTwo.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        /* 代码执行6:
                * 1.在Activity中通过Fragment对象调用其中的方法。*/
        mFragmentTwo.Amend();
    }
});
mButtonDeleteFragmentNow.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        /* 代码执行6:
                * 1.如果你希望删除Fragment,则使用remove方法即可,通过将Fragment对象作为参数。。*/
        getSupportFragmentManager().beginTransaction()
            .remove(mFragmentNow).commit();
    }
});

以下代码在MainActivity中写入:

/* 代码执行6:
    * 1.同理,在Activity中创建公共方法,用于Fragment中调用。*/
public void Amend() {
    TextView textView = (TextView) findViewById(R.id.TextView);
    textView.setText("你看吧,Activity中的TextView已经被修改了。");
}

至此,Fragment中的基本使用你已经学会了,其实Fragment还有一种静态添加的方式,不过个人认为此种方式使用不够灵活,且也非常简单,便没有在文章中写出,感兴趣的话可以查看相关文章。
现在再来看一下效果图,你的效果是否一致?

用于操作Fragment的其他方法:
比较常用的操作Fragment的方法在前面的案例中已经有说明了,不过还有一些没有使用到的需要唠叨两句。

  • .add()

该方法是用于创建Fragment的,但是当你创建过一次Fragment后,再点击一次,则会抛出异常,不能创建第二次。所以Demo中就没有使用这种方式。

  • .replace()

replace()其实是先删除,再创建,如果不考虑Fragment中的临时数据的话,可以使用这种方式来创建Fragment。

  • .hide()

这个方法仅仅是将Fragment隐藏起来,但并不是将其销毁。

  • .show()

同样的,是将隐藏起来的Fragment显示出来。

Fragment与Activity进行通信

​ 前面使用了通过对象之间调用方法来使Fragment和Activity进行通信,但这样做的局限性在于,无法对方法进行统一处理。例如,在使用多个Fragment时,希望在原有Fragment的基础上统一添加一些功能,通过方法是不能高效的完成的。这时通过接口,既可以使Fragment和Activity进行数据传递,也可以统一添加功能。  以下代码将以实现Fragment与Activity数据传递为中心,穿插说明显示/隐藏Fragment、在Activity中集中管理Fragment。

以下为效果图:

准备工作:

即分别创建Activity与Fragment的布局文件,代码分别如下:
以下代码在MainActivity的布局文件中写入:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/TextViewShowFragment"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:layout_gravity="center_vertical"
        android:text="这里是MainActivity"
        android:textSize="18sp" />

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

</LinearLayout>

以下代码在SetFragment的布局文件中写入:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:layout_marginRight="10dp"
        android:layout_marginLeft="10dp"
        android:orientation="vertical">

        <Button
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:id="@+id/ButtonMy"
            android:text="我的信息"
            android:background="@null"
            android:textSize="16sp"
            android:textColor="#535252"
            android:layout_marginTop="5dp"/>
    </LinearLayout>
</LinearLayout>

以下代码在MyFragment的布局文件中写入:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/ButtonReturn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@null"
        android:text="返回" />

    <TextView
        android:id="@+id/TextViewNumber"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:textColor="#FF00"
        android:textSize="100sp" />
</LinearLayout>

接着来讨论一下本篇代码的思路:

  • 1.首先创建一个父类,用于Fragment继承并使用其中的接口。
  • 2.初始化Activity以及两个Fragment。
  • 3.在SetFragment中完成对接口的应用。
  • 4.通过Handler和定时器使MyFragment有自己的逻辑处理。
  • 5.在MainActivity中分别创建创建、隐藏、显示Fragment的方法。
  • 6.在MainActivity中分别创建监听SetFragment和MyFragment接口的方法。

详细代码:
以下代码新建FragmentInterface类后写入:

public class FragmentInterface extends Fragment {

    public interface ReturnNowFragmentName {
        void returnNowFragmentName(String fragmentName);
    }

    public ReturnNowFragmentName mReturnNowFragmentName;

    public void ListenerNowFragmentName(ReturnNowFragmentName returnNowFragmentName) {
        mReturnNowFragmentName = returnNowFragmentName;
    }

    public interface OnButtonClickListener {
        void onButtonClickListener();
    }

    public OnButtonClickListener mButtonClickListener;

    public void ListenerButtonClick(OnButtonClickListener onButtonClickListener) {
        mButtonClickListener = onButtonClickListener;
    }
}
  • 1.1.这个类继承自Fragment,这是因为希望我们使用的Fragment处本身的功能外具有其他一些功能。
  • 1.2.但是必须是类的形式,而不是接口,因为接口无法继承自一个类。
  • 2.1.首先定义一个接口,在接口中写入一个方法,这个方法的参数可以给Activity提供当前Fragment的类名。
  • 2.2.这便是使用接口使Activity同Fragment进行数据的传输。
  • 2.3.接着使用接口作为数据类型,创建一个该接口的对象,用于Activity和Fragment调用接口使用。
  • 2.4.最后添加一个方法,该方法是用于在MainActivity中重写接口时需要的方法,在该方法中将接口通过匿名类的方式初始化(使用)。
  • 3.再使用同一的方法重写监听Button按钮的接口,用于在Activity中处理关于Fragment对Fragment进行的操作(其他操作可以在Fragment中自行定义)。

以下代码新建SetFragment类后写入:

public class SetFragment extends FragmentInterface {
    private Button mButtonMy;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.set_fragment, null);
        mButtonMy = (Button) view.findViewById(R.id.ButtonMy);
        mReturnNowFragmentName.returnNowFragmentName(getClass().getName());
        return view;
    }
}
  • 1.首先通过View绑定Fragment的Layout布局文件以及初始化按钮。
  • 2.1.然后通过父类中的接口对象,调用该接口,并且传入当前类的名称作为参数。
  • 2.2.这时如果运行程序,则会报空指针异常,这是因为此时仅仅定义了接口中的参数,但还没有对接口进行初始化。

以下代码新建SetFragment类后写入:

public class MyFragment extends FragmentInterface {
    private TextView mTextViewNumber;
    private Button mButtonReturn;
    private int number;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.my_fragment, null);
        mTextViewNumber = (TextView) view.findViewById(R.id.TextViewNumber);
        mButtonReturn = (Button) view.findViewById(R.id.ButtonReturn);
        mReturnNowFragmentName.returnNowFragmentName(getClass().getName());
        return view;
    }
}

以下代码MainActivity中写入:

    private void init() {
        mTextView = (TextView) findViewById(R.id.TextViewShowFragment);
        mSetFragment = new SetFragment();
        mMyFragment = new MyFragment();
    }

记得在onCreate()中调用init()。

以下代码SetFragment中写入:

    @Override
    public void onStart() {
        super.onStart();

        mButtonMy.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mReturnNowFragmentName.returnNowFragmentName(new MyFragment().getClass().getName());
                mButtonClickListener.onButtonClickListener();
            }
        });
    }
  • 1.1.写入Button的监听事件,当点击按钮后,就分别调用两个接口。使Activity中得到需要处理重写的接口的通知。
  • 1.2.值得注意的是,返回FragmentName的接口,需要以该Fragment启动的Fragment的名称作为参数。
  • 1.3.这是因为如果不这样做,就会导致显示的类名和显示的Fragment不一致。
  • 1.4.并且写了一个getClassName(),也可以在MyFragment中通过调用该方法来获取类名。(进行了封装)
  • 1.5.这也是Fragment之间通信的另外一种方式。
  • 1.6.你可能会考虑到,在初始化Fragment时已经定义了返回名称的接口,为什么在点击事件后又重写调用。
  • 1.7.这是因为onCreate()或者onCreateView()只会在创建时调用一次,而后续再希望实时根据当前类名改变TextView内容时就必须每次点击Button时再调用一次。

以下代码MyFragment中写入:

    @Override
    public void onStart() {
        super.onStart();

        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                mTextViewNumber.setText(number++ + "");
            }
        };

        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                handler.sendEmptyMessage(100);
            }
        }, 0, 1000);

        mButtonReturn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mReturnNowFragmentName.returnNowFragmentName(new SetFragment().getClassName());
                mButtonClickListener.onButtonClickListener();
            }
        });
    }
  • 1.1.通过Timer()定时器以及Handler配合完成定义修改UI组件的功能。
  • 1.2.不能直接使用Timer()来修改UI组件,这是由于Timer()是一个新的线程,而Android只允许在主线程中修改UI。
  • 2.1.首先创建Handler,并重写handleMessage(),该方法的参数是一个Key值。后续会单开一篇来讨论Handler。
  • 2.2.现在只需在Handler直接写入给当前用于显示数值的变量++即可。
  • 3.1.在Timer()中,调用Handler对象,发送一个空的消息,参数即是Key值。
  • 3.2.0和1000分别是,第一次调用延时多少毫秒,后续每多少毫秒执行一次。

以下代码MainActivity中写入:

private void addFragment(Fragment fragment) {
        getSupportFragmentManager().beginTransaction().add(R.id.FrameLayout, fragment).commit();
    }

    private void hideFragment(Fragment fragment) {
        getSupportFragmentManager().beginTransaction().hide(fragment).commit();
    }

    private void showFragment(Fragment fragment) {
        getSupportFragmentManager().beginTransaction().show(fragment).commit();
    }
  • 1.通过同样的格式分别创建添加、隐藏、显示的方法。并且方法接受一个Fragment类型的对象作为参数,用于处理当前Fragment。
  • 2.值得注意的是,每个FragmentTransaction只能提交一次事务,即每次使用FragmentTransaction都需要将其初始化。
  • 3.在添加方法中,不能使用replace(),因为我们需要Fragment在后台继续工作,而不是直接将其销毁。

以下代码MainActivity中写入:

private void setSetFragment() {
        mSetFragment.ListenerNowFragmentName(new FragmentInterface.ReturnNowFragmentName() {
            @Override
            public void returnNowFragmentName(String fragmentName) {
                StringBuffer string = new StringBuffer();
                string.append(fragmentName).delete(0,12);
                mTextView.setText("现在打开的是:" + string.toString());
            }
        });

        mSetFragment.ListenerButtonClick(new FragmentInterface.OnButtonClickListener() {
            @Override
            public void onButtonClickListener() {
                if (mMyFragment.isHidden() == true) {
                    hideFragment(mSetFragment);
                    showFragment(mMyFragment);
                } else {
                    addFragment(mMyFragment);
                    hideFragment(mSetFragment);
                }
            }
        });
    }

    private void setMyFragment() {
        mMyFragment.ListenerNowFragmentName(new FragmentInterface.ReturnNowFragmentName() {
            @Override
            public void returnNowFragmentName(String fragmentName) {
                StringBuffer string = new StringBuffer();
                string.append(fragmentName);
                string.delete(0, 12);
                mTextView.setText("现在打开的是:" + string.toString());
            }
        });

        mMyFragment.ListenerButtonClick(new FragmentInterface.OnButtonClickListener() {
            @Override
            public void onButtonClickListener() {
                showFragment(mSetFragment);
                hideFragment(mMyFragment);
            }
        });
    }
  • 1.1.首先初始化FragmentName接口的方法,值得注意的是,默认情况下getClass().getName()返回的不仅是类名,还有包名。
  • 1.2.所以通过StringBuffer对象来处理一下字符串。(好像跑题了)
  • 1.3.通过append()添加一个字符串,通过delete来删除字符串中的固定位置的内容。0为起始位置,12为结束位置。
  • 2.1.在处理setFragment的按钮点击时,需要先判断MyFragment是否被隐藏,如果被隐藏,则隐藏SetFragment,显示MyFragment。
  • 2.2.如果没有被隐藏,就创建MyFragment,然后隐藏SetFragment。切记添加判断,否则会乱套的…

Fragment以及Activity的分工

​ 众所周知,Fragment是依赖于Activity的,这样做的初衷是,在一个页面中,如果所有的组件、逻辑全部放在一个Activity中,这会使原本庞大的Activity变的更为臃肿,所以通过Fragment,在界面中,Activity只需要创建、显示、隐藏、管理Fragment就可以了。其他组件的逻辑全部放在对应的Fragment中。 也就是说,Activity用来管理Fragment,Fragment管理其他的组件。
另外,网上很多说的不要对Fragment进行嵌套的问题,这是由于Fragment的生命周期比Activity还要复杂,而且Android会自动对长期不在前台的Activity或Fragment进行销毁,这样,依然存在前台的Fragment的依赖于其他Activity或者Fragment的,但此时它所依赖的Activity或Fragment已经被销毁了。在以上案例中,当开启MyFragment计数功能后,对屏幕进行翻转,就会报出异常,这是因为,MainActivity已经被销毁,此时又重新建立,而MyFragment此时仍在活动状态,但是它依附的Activity已经不再是原来的Activity了。
此外,不能嵌套Fragment并不是指不允许一个Fragment打开另外一个Fragment,可以通过getActivity().getLocalClassName()来查看Fragment所依赖的Activity。

猜你喜欢

转载自www.cnblogs.com/zhouheng0918/p/9209119.html