在FragmentPagerAdapter中动态添加删除片段会导致null异常

时间:2016-05-10 08:53:59

标签: java android android-fragments fragment android-tablayout

我有一个应用程序,我有几个片段,其中一些需要动态添加或删除。所以我从2个片段开始。登录后,我删除1个片段并添加2或3个。根据其他行动,这可能会在应用程序的生命周期中发生变化。

每个片段都显示在带标题的标签中。

我的主要活动布局如下所示;

<android.support.design.widget.CoordinatorLayout 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:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="net.kaisersmith.whereami.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/appbar_padding_top"
        android:theme="@style/AppTheme.AppBarOverlay">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:layout_scrollFlags="scroll|enterAlways"
                app:popupTheme="@style/AppTheme.PopupOverlay">

            </android.support.v7.widget.Toolbar>

            <android.support.design.widget.TabLayout
                android:id="@+id/sliding_tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:tabMode="scrollable" />
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_margin="@dimen/fab_margin"
        android:src="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>

我正在使用FragmentPagerAdapter,我可以添加片段。但当我删除它们似乎工作正常但不是。选项卡标题是正确的,但当我尝试移动到另一个选项卡时,我得到一个例外。例外是;

Java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.app.FragmentManagerImpl.performPendingDeferredStart(android.support.v4.app.Fragment)' on a null object reference
    at android.support.v4.app.Fragment.setUserVisibleHint(Fragment.java:876)
    at android.support.v4.app.FragmentPagerAdapter.setPrimaryItem(FragmentPagerAdapter.java:130)
    at android.support.v4.view.ViewPager.populate(ViewPager.java:1175)
    at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:608)
    at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:570)
    at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:551)
    at android.support.design.widget.TabLayout$ViewPagerOnTabSelectedListener.onTabSelected(TabLayout.java:2008)
    at android.support.design.widget.TabLayout.selectTab(TabLayout.java:1025)

从我的页面查看器中提取

public class SectionsPagerAdapter extends FragmentPagerAdapter {
...
 public void addFragment(Fragment frag, String title)
    {
        if (!this.fragments.contains(frag))
        {
            this.fragments.add(frag);
        }
        this.notifyDataSetChanged();
    }
...
public void removeFragment(String title)
    {
        Fragment frag = findFragmentByTitle(title);

        if (frag != null)
        {
            this.fragments.remove(frag);

            //String tag = this.fragments.get(loc).getTag();
            //Fragment fragment = this.getFragmentManager().findFragmentByTag(tag);
            if(frag != null)
                this.getFragmentManager().beginTransaction().remove(frag).commit();
        }
    }

这是从我的主要活动中调用的;

mSectionsPagerAdapter.addFragment(new LoginFragment(),"Sign in");
mSectionsPagerAdapter.removeFragment("Logout");
mSectionsPagerAdapter.notifyDataSetChanged();

我在互联网上看了很多例子,但大多数都是基本的,并且有固定的片段不会改变。或者如何添加/删除片段的示例不会以其他方式工作。

隐藏碎片&amp;标签将是另一种选择,但据我所知,它无法在工具栏中隐藏它们

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

我遇到了同样的期望,但我的代码却不同。

        viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
        @Override
        public Fragment getItem(int position) {

            return fragments[position];
        }

        @Override
        public int getCount() {
            return fragments.length;
        }
    });

fragments是一个片段数组。 当我调试时,我发现fragment.mActivity上的FragmentPagerAdapter.instantiateItem()为空。

答案 1 :(得分:0)

尝试这样做:

class ViewPagerAdapter extends FragmentPagerAdapter {

    private FragmentManager mManager;
    private final List<Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();

    public ViewPagerAdapter(FragmentManager manager) {
        super(manager);
        this.mManager = manager;
    }

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

    @Override
    public int getCount() {
        return mFragmentList.size();
    }

    public void addFrag(Fragment fragment, String title) {
        mFragmentList.add(fragment);
        mFragmentTitleList.add(title);
        notifyDataSetChanged();
    }

    public void removeFragment(int position) {
        mFragmentTitleList.remove(position);
        mManager.beginTransaction().remove(mFragmentList.get(position)).commit();
        mFragmentList.remove(position);
        notifyDataSetChanged();
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitleList.get(position);
    }

}

答案 2 :(得分:0)

在FragmentTransaction中使用replace方法添加&amp;删除

private void transactFragment(Fragment fragment) {
        if (fragment != null) {
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.replace(R.id.container_body, fragment);
            fragmentTransaction.commit();

        }
    }

使用我重新启动用户framelayout作为视图容器添加&amp;替换片段。