java - onBackStackChanged() 在 backstack 中添加新 fragment 时调用两次

标签 java android android-fragments android-view fragmentmanager

所以,我注意到一个有趣的问题。当我以编程方式添加新 fragment 时,来自 OnBackStackChangedListener 的方法 onBackStackChanged 被调用两次,但它只能被调用一次。这是我的 Activity 代码:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements FragmentManager.OnBackStackChangedListener{

    private FragmentManager fragmentManager;
    private Button button1;
    private Button button2;
    private Button button3;

    private Fragment defaultFragment;
    private Fragment previousFragment;
    private Fragment currentFragment;
    private String currentFragmentTag;

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

        button1 = (Button) findViewById(R.id.button);
        button2 = (Button) findViewById(R.id.button2);
        button3 = (Button) findViewById(R.id.button3);

        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showFragment(new FragmentOne(), FragmentOne.TAG);
            }
        });

        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showFragment(new FragmentTwo(), FragmentTwo.TAG);
            }
        });

        button3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showFragment(new FragmentThree(), FragmentThree.TAG);
            }
        });

        setupFragmentManager();

    }

    private void setupFragmentManager() {
        fragmentManager = getSupportFragmentManager();
        fragmentManager.addOnBackStackChangedListener(this);


        FragmentOne fragmentOne = new FragmentOne();
        defaultFragment = fragmentOne;  // fragment for default

        currentFragmentTag = FragmentOne.TAG;
        currentFragment = fragmentOne;

        fragmentManager.beginTransaction()
                .add(R.id.fragments_container, currentFragment, currentFragmentTag)
                .addToBackStack(currentFragmentTag)
                .commit();
    }

    public void showFragment(Fragment fragment, String fragmentTag) {
        previousFragment = currentFragment;
        currentFragment = fragment;
        fragmentManager.beginTransaction()
                .hide(previousFragment)
                .add(R.id.fragments_container, fragment, fragmentTag)
                .addToBackStack(fragmentTag)
                .commit();
    }

    @Override
    public void onBackStackChanged() {
        Log.d("MY_TAG" , "onBackStackChangedListener - " + fragmentManager.getBackStackEntryCount() );

        if (fragmentManager.getBackStackEntryCount() > 0) {    
            String fragmentTag = fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount() - 1).getName();
            currentFragment = fragmentManager.findFragmentByTag(fragmentTag);
        } else {
            currentFragment = defaultFragment;
        }

// some code...
    }

    @Override
    public void onBackPressed() {
        if (fragmentManager.getBackStackEntryCount() == 1) { 
            finish();
        } else {
            super.onBackPressed();
        }
    }
}

和 fragment 类:

public class FragmentOne extends Fragment {

    public static final String TAG = FragmentOne.class.getSimpleName();

    private Context context;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {


        context = getActivity();
        View topLevelView = LayoutInflater.from(context).inflate(R.layout.fragment_layout, container, false);

        TextView textView = (TextView) topLevelView.findViewById(R.id.fragment_Text);

        textView.setText("This is FRAGMENT ONE");

        return topLevelView;
    }

}

FragmentTwo 和 FragmentThree 与 FragmentOne 相同。

当我启动我的应用程序时,我在日志中看到:

onBackStackChangedListener - 1
onBackStackChangedListener - 1

按下按钮后(显示下一个 fragment )我看到:

onBackStackChangedListener - 2
onBackStackChangedListener - 2

还有一个:

onBackStackChangedListener - 3
onBackStackChangedListener - 3

不断变化

.add(R.id.fragments_container, currentFragment, currentFragmentTag)

.replace(R.id.fragments_container, currentFragment, currentFragmentTag)

没有解决问题。

但是很奇怪。为什么我的 OnBackStackChangedListener 在一次添加 fragment 后多次调用自己的方法?

最佳答案

不敢相信这会发生。创建了一个类似的项目并深入调试器。原来这是新支持库中的错误。有一个bug opened in the tracker .

切换回 25.0.0 将按预期工作。

compile 'com.android.support:appcompat-v7:25.0.0'
compile 'com.android.support:support-v4:25.0.0'

虽然在release notes中没有提到, 但提到了 in the issue tracker ,该问题已在 25.4.0 中修复,这很好 😊。

关于java - onBackStackChanged() 在 backstack 中添加新 fragment 时调用两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42937981/

相关文章:

java - 制作合适的 Java 数独生成器的问题

java - 如何更改 JavaFX 中的 TableView 框架颜色?

java - 将字符串转换为日期错误

Android导航组件不显示 fragment

android - 方向更改后以编程方式截取屏幕截图

java - 使用相同的 body 标签将两个不同的 fragment 添加到两个布局中?

java - 如果方法以 invoke 启动,Exceptions 不会导致崩溃

java - 如何检查java swing中的当前窗口大小?

android - 如何使用字符串作为代码?

android - 如何确定Android中的当前时间?