片段中的元素在 re-adding 相同片段后不起作用

Elements in Fragment not working after re-adding the same fragment

UPDATE:我发现 header 不是唯一受影响的东西,但 listeners 和片段中的其他元素没有受到影响初始化。 (例如 FAB)。唯一能正常运行的是 adapter(即 ListView 行)

中内置的所有内容

问题:打开导航抽屉,单击一个列表项,在同一个 Activity 中打开一个新的 Fragment。再次打开导航抽屉,单击应该简单地替换现有 Fragment 的相同项目,当 Fragment 打开时,所有在 Java 中以编程方式设置的元素(文本、颜色, listeners) 不是 changed/added 到 Fragment。该视图只是默认的 xml 布局。我已经用 Log.d 确认设置这些东西的代码 是 运行。 (如果你打开一个不同的Fragment然后回到原来的那个,一切正常)

确认的原因: 更改时:

    compile "com.android.support:appcompat-v7:25.0.1"
    compile 'com.android.support:design:25.0.1'

    compile "com.android.support:appcompat-v7:25.1.0"
    compile 'com.android.support:design:25.1.0'

(如果只改了其中一个库,不管哪个,问题依旧)

我已经确认更改这两个库是问题所在(也在第二个应用程序中确认了这个问题——并且仅更改 这段代码,具有完全相同的结果)

我的问题是,为什么会发生这种情况,如何解决?

原始问题的代码和更详细的描述:

                FragmentTransaction tItems = fm.beginTransaction();
                ListFragment mFrag = new PlannerFragment();
                tItems.replace(R.id.main_frag, mFrag, TAG_CALC_FRAGMENT);
                tItems.commit();

我的抽屉里大约有4个选项都打开了这个Fragment,但在每个选项之前,我都设置了一个全局变量,如下所示:

MyApp.PlanType = "highbal";
MyApp.PlanType = "lowbal";
etc.

基于 PlanType 值(以上),Fragment 加载了不同的数据(但是,在完全相同的 xml 布局中)。它只是一个 ListView 和一个 header.

Fragment,(PlannerFragment) 第一次加载正常。

当我单击另一个项目(不同的 PlanType)时,它转到相同的 Fragment(上面执行的相同代码):ListView 在实际列表中加载正常。 但是 header 列表中, none 的 setText() 值正确设置了新数据。它使用我的 xml 布局中的默认值。

现在,如果我在两者之间加载不同的 Fragment,一切都会很好。只有当我在旧的上面添加或替换(我都试过)相同的 Fragment 时才会发生这种情况。

这是 PlannerFragment

顶部的 header 代码
@Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        // Setup listview
        lv = getListView();

        LayoutInflater inflaterHeader = getActivity().getLayoutInflater();
        ViewGroup header = (ViewGroup) inflaterHeader.inflate(R.layout.planner_listview_header, lv, false);
        lv.addHeaderView(header, null, false);

        // Load Data then Set Textviews, e.g.:
        TextView title = (TextView) getActivity().findViewById(R.id.tvPlannerTitle);
    dateOutput = (TextView) getActivity().findViewById(R.id.tvDebtOutDate);

如果我添加到该代码,dateOutput.setText("test"); 它不会发生。我可以做一个 Log.d 和我的数据寄存器,所以正在读取这段代码,但是 UI 没有设置。

我什至试过先删除 Fragment 像这样检查:

                Fragment fragment = fm.findFragmentByTag(TAG_CALC_FRAGMENT);
                if(fragment != null)
                    fm.beginTransaction().remove(fragment).commit();

这没有效果。

同样,这只发生在我更改上面的库时。这是库的错误还是它现在的响应不同?

appcompat 25.1.0 上的片段有许多 变化和问题。第一个似乎与您的问题有关,但应该阅读下两个,因为它可能很重要。


FragmentTransaction 替换行为

替换在 appCompat 25.1.0 中无法正常工作
当前状态(2017 年 1 月 4 日):bug 已分配
Issue link


25.1.0 上的片段生命周期更改

新片段的 onStart 在前一个片段的 onStop 之前被调用
当前状态:按预期工作。对我来说,这可能是 app compat 25 的重大变化。0.x Issue link

在片段中 调用两次 的恢复事件也存在问题,请参阅 here

TLDR. 也许最好的临时解决方案是在新版本发布之前不要使用 25.1.0。

您可以在 navigationDrawer() 方法中添加 list_view_header.xml 并更改所选项目的位置,例如 selectItem(position - 1)

  private void navigationDrawer() {

        mTitle = mDrawerTitle = getTitle();
        // mNavigationDrawerItemTitles = getResources().getStringArray(R.array.navigation_drawer_items_array);

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.left_drawer);

        LayoutInflater inflater = getLayoutInflater();
        View listHeaderView = inflater.inflate(R.layout.list_view_header, null, false);
        mDrawerList.addHeaderView(listHeaderView, null, false);

        setupToolbar();

        DataModel[] drawerItem = new DataModel[6];

        drawerItem[0] = new DataModel(R.drawable.dashboard_icon, "Dashboard");
        drawerItem[1] = new DataModel(R.drawable.cal_icon, "Calender");
        drawerItem[2] = new DataModel(R.drawable.classes, "Classes");
        drawerItem[3] = new DataModel(R.drawable.message_icon_hdpi, "Message Center");
        drawerItem[4] = new DataModel(R.drawable.profile, "Profile & Setting");
        drawerItem[5] = new DataModel(R.drawable.bulletin_icon, "Bulletin Board");

        getSupportActionBar().setDisplayHomeAsUpEnabled(false);
        getSupportActionBar().setHomeButtonEnabled(true);

        DrawerItemCustomAdapter adapter = new DrawerItemCustomAdapter(this, R.layout.list_view_item_row, drawerItem);
        mDrawerList.setAdapter(adapter);
        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerLayout.setDrawerListener(mDrawerToggle);
        setupDrawerToggle();


    }

    private class DrawerItemClickListener implements ListView.OnItemClickListener {

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            selectItem(position - 1);
        }


    }

    private void selectItem(int i) {
        Fragment fragment = null;

        switch (i) {
            case 0:
                fragment = new Fragment_DashBoard();
                // toolbar.setTitle("Dashboard");
                Titletv.setText("Dashboard");
                break;
            case 1:
                fragment = new Fragment_Calender();
                // toolbar.setTitle("Calender");
                Titletv.setText("Calender");

                break;
            case 2:
                fragment = new Fragment_Classes();
                // toolbar.setTitle("Classes");
                Titletv.setText("Classes");
                break;
            case 3:
                fragment = new Fragment_MessageCenter();
                // toolbar.setTitle("Message");
                Titletv.setText("Messages");
                break;
            case 4:
                fragment = new Fragment_ProfileSetting();
                // toolbar.setTitle("Profile");
                Titletv.setText("Profile");

                break;

            case 5:
                fragment = new Fragment_BulletinBoard();
                //toolbar.setTitle("Bulletin Board");
                Titletv.setText("Bulletin Board");

                break;

            default:
                break;
        }


        if (fragment != null) {

            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction trans = fragmentManager.beginTransaction();
            fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).addToBackStack(null).commit();

            mDrawerList.setItemChecked(i, true);
            mDrawerList.getItemAtPosition(i);
            // setTitle(mNavigationDrawerItemTitles[position]);
            mDrawerLayout.closeDrawer(mDrawerList);


        } else {
            Log.e("MainActivity", "Error in creating fragment");
        }


    }