欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

FragmentManager的简单使用

程序员文章站 2022-04-15 18:43:49
...

本文查看一下使用fragmentmanager的hide(),show()方法后,fragment执行了什么生命周期
本文创建一个主活动,两个附属的fragment,代码如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private String tag = "debug";
public Fragment1 fragment1;
    public Fragment2 fragment2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        Button button1=findViewById(R.id.button1);
        Button button2=findViewById(R.id.button2);
button1.setOnClickListener(this);
button2.setOnClickListener(this);
        Log.d(tag, "oncreate");

    }
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.button1:
                fragment1=new Fragment1();
                getSupportFragmentManager().beginTransaction().add(R.id.container,fragment1).commit();
                break;
            case R.id.button2:
                fragment2=new Fragment2();
                getSupportFragmentManager().beginTransaction().hide(fragment1).commit();
                getSupportFragmentManager().beginTransaction().add(R.id.container,fragment2).commit();
                break;
        }

    }
    @Override
    protected void onStart () {
        Log.d(tag, "onstart");
        super.onStart();
    }

    @Override
    protected void onStop () {
        Log.d(tag, "onstop");
        super.onStop();
    }

    @Override
    protected void onDestroy () {
        Log.d(tag, "ondestroy");
        super.onDestroy();
    }

    @Override
    protected void onPause () {
        Log.d(tag, "onpause");
        super.onPause();
    }

    @Override
    protected void onResume () {
        Log.d(tag, "onresume");
        super.onResume();
    }

}
package com.example.test.fragment;

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

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

import com.example.test.MainActivity;
import com.example.test.R;

public class Fragment1 extends Fragment {
    String tag="debug";
public TextView textView;
public void ran(){
    ;
}
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Log.d(tag,"oncreateview1");
        View view=inflater.inflate(R.layout.fragment1,container,false);
textView=view.findViewById(R.id.textView);
        return view;

    }

    @Nullable

    @Override
    public void onAttach(@NonNull Context context) {
        Log.d(tag,"onattachf1");
        super.onAttach(context);

    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        Log.d(tag,"oncreatef1");
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        Log.d(tag,"onacitvitycreated");
        super.onActivityCreated(savedInstanceState);

    }

    @Override
    public void onStart() {
        Log.d(tag,"onstartf1");
        super.onStart();
    }

    @Override
    public void onResume() {
        Log.d(tag,"onresumef1");
        super.onResume();
    }

    @Override
    public void onPause() {

        Log.d(tag,"onpausef1");
        super.onPause();
    }

    @Override
    public void onStop() {
        Log.d(tag,"onstopf1");
        super.onStop();
    }

    @Override
    public void onDestroyView() {
        Log.d(tag,"ondestroyviewf1");
        super.onDestroyView();
    }

    @Override
    public void onDestroy() {
        Log.d(tag,"ondestroyf1");
        super.onDestroy();
    }

    @Override
    public void onDetach() {
        Log.d(tag,"ondetachf1");
        super.onDetach();
    }
}

package com.example.test.fragment;

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.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

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

import com.example.test.MainActivity;
import com.example.test.R;

public class Fragment2 extends Fragment implements View.OnClickListener{
    String tag="debug";
    MainActivity mainActivity;
    TextView text;
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Log.d(tag,"oncreateview2");
        View view=inflater.inflate(R.layout.fragment2,container,false);
      mainActivity= (MainActivity) getActivity();
Button button=view.findViewById(R.id.button);
button.setOnClickListener(this);
 text=view.findViewById(R.id.textView);
     
        return view;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.button:
                TextView textView=mainActivity.fragment1.textView;

text.setText(textView.getText().toString());
                break;
        }
    }


    @Nullable

    @Override
    public void onAttach(@NonNull Context context) {
        Log.d(tag,"onattachf2");
        super.onAttach(context);

    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        Log.d(tag,"oncreatef2");
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        Log.d(tag,"onacitvitycreatedf2");


        super.onActivityCreated(savedInstanceState);
    }

    @Override
    public void onStart() {
        Log.d(tag,"onstartf2");
        super.onStart();
    }

    @Override
    public void onResume() {
        Log.d(tag,"onresumef2");
        super.onResume();
    }

    @Override
    public void onPause() {

        Log.d(tag,"onpausef2");
        super.onPause();
    }

    @Override
    public void onStop() {
        Log.d(tag,"onstopf2");
        super.onStop();
    }

    @Override
    public void onDestroyView() {
        Log.d(tag,"ondestroyviewf2");

        super.onDestroyView();
    }

    @Override
    public void onDestroy() {
        Log.d(tag,"ondestroyf2");

        super.onDestroy();
    }

    @Override
    public void onDetach() {
        Log.d(tag,"ondetachf2");
        super.onDetach();
    }


}

他们的布局文件并不需要展示,等下看运行截图就知道了。此处测试的核心代码是:

    fragment2=new Fragment2();
                getSupportFragmentManager().beginTransaction().hide(fragment1).commit();
                getSupportFragmentManager().beginTransaction().add(R.id.container,fragment2).commit();

然后截图如下,这里的截图已经依次点击了按钮1和按钮2(事务请看MainAcitivity代码),并且点击了获取按钮3(点击按钮3其实就是为了查看这个fragment1的textview会不会因为hide而被销毁,所以此处在fragment2中测试下能不能获取那个textview中的内容,此处显示可以,fragment1的布局文件中textview的内容就是“fragment1中的数据”,也就是没有因为hide而销毁):
FragmentManager的简单使用生命周期执行情况可以继续证明如下:
FragmentManager的简单使用
也即是说原来的fragment1还是在运行中的。
下面改变MainActivity中的onClick方法,如下(只改了一点点,表示把fragment1和2加入到返回栈):

  @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.button1:
        
                fragment1=new Fragment1();
                getSupportFragmentManager().beginTransaction().add(R.id.container,fragment1).addToBackStack(null).commit();
                break;
            case R.id.button2:
                fragment2=new Fragment2();
                getSupportFragmentManager().beginTransaction().hide(fragment1).commit();
                getSupportFragmentManager().beginTransaction().add(R.id.container,fragment2).addToBackStack(null).commit();
                break;
        }

    }

再次运行,结果当然一样,这次操作只是额外manager把他们加入到返回栈而已。下面组另外测试,查看返回键对fragment的影响。按返回键,和平常你测试的时候只有一个MainAcitvity的时候按返回键会直接销毁是一样的。下面进行验证,按一次返回键后,也就是让fragment2出栈,生命周期执行情况为:
FragmentManager的简单使用
和预料的一样,但是此时fragment1布局中的内容却没有显示,为什么呢?按理此时栈顶是fragment1了啊,其实是我代码写错了,或者没有理解到fragmentmanager加入返回栈的含义,下面看下源码注释是怎么说的:

/**
* Add this transaction to the back stack. This means that the transaction
* will be remembered after it is committed, and will reverse its operation
* when later popped off the stack.
*


* {@link #setReorderingAllowed(boolean)} must be set to true
* in the same transaction as addToBackStack() to allow the pop of that
* transaction to be reordered.
*
* @param name An optional name for this back stack state, or null.
*/

也就是说是把这次事务保存了一下,下次返回是返回到这次事务之前,而一次一次事务是按commit()来计算的,我前面代码那里,用了两个commit(),所以回到的是第二个之前的那个状态,也就是回到还没有加入fragment2之前的状态,所以你按返回键会销毁fragment2。但是这个状态在第一个commit()之后,此时fragment1已经隐藏了,所以就没有显示了。
下面修改代码,正确显示。

 fragment2=new Fragment2();
                getSupportFragmentManager().beginTransaction().hide(fragment1).commit();
                getSupportFragmentManager().beginTransaction().add(R.id.container,fragment2).addToBackStack(null).commit();
                break;

修改为

 fragment2=new Fragment2();
                getSupportFragmentManager().beginTransaction().hide(fragment1);
                getSupportFragmentManager().beginTransaction().add(R.id.container,fragment2).addToBackStack(null).commit();

之后重新运行,在按返回键之前,发现显示fragment2的时候发生了重叠,fragment1难道没有隐藏?是的,上面代码还是有问题,因为上面有两次事务,而第一事务没有提交,所以无效。之后按返回键,预测一下结果?是正确的,正确回到fragment1,fragment2被销毁。
下面再改正重叠问题,上面改为:

 fragment2=new Fragment2();

                getSupportFragmentManager().beginTransaction().hide(fragment1).add(R.id.container,fragment2).addToBackStack(null).commit();

或者不想那么长,等价改为:

    fragment2=new Fragment2();
FragmentManager fragmentManager=getSupportFragmentManager();
FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
fragmentTransaction.hide(fragment1);
fragmentTransaction.add(R.id.container,fragment2);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();

这是因为源码返回值基本都还是一个FragmentTransaction,例如hide():

 @NonNull
    public FragmentTransaction hide(@NonNull Fragment fragment) {
        addOp(new Op(OP_HIDE, fragment));

        return this;
    }

总结:所以hide()和show(),以及加入返回栈都不会影响fragment的生命周期,不会被销毁,replace()方法则另当别论哦。这两个方法我喜欢用来制作一个主页面,点击下面菜单,切换不同的页面,就像QQ那样,刚进入活动时创建这几个fragment页面,然后单机后用hide,show不停切换。
FragmentManager的简单使用
如果有什么问题,欢迎留言交流。

相关标签: 安卓开发 安卓