使用getChildFragmentManager()时的空对象引用.beginTransaction()

时间:2017-06-29 04:05:15

标签: android android-fragments fragment fragmentmanager

我使用FragmentPagerAdapter在我的ViewPgaer中有4个片段。我尝试在持续延迟后添加每个片段,以便在切换底栏选项卡时获得无混蛋动画。

我使用this库作为具有移动动画的底栏。所有四个片段都有多个api调用,如果我在延迟后没有添加它们,那么移动动画就会生涩。

问题是我收到了一个难以复制的错误日志(如下所示)。

错误日志:

    Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Class java.lang.Object.getClass()' on a null object reference
   at android.support.v4.app.BackStackRecord.doAddOp(BackStackRecord.java:380)
   at android.support.v4.app.BackStackRecord.add(BackStackRecord.java:369)
   at com.vanitee.services.view.FragmentFake$1.run(FragmentFake.java:46)
   at android.os.Handler.handleCallback(Handler.java:761)
   at android.os.Handler.dispatchMessage(Handler.java:98)
   at android.os.Looper.loop(Looper.java:156)
   at android.app.ActivityThread.main(ActivityThread.java:6585)
   at java.lang.reflect.Method.invoke(Method.java)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:941)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:831)

ViewPagerAdapterClass:

    class MyAccountPagerAdapter extends FragmentPagerAdapter {

    public MyAccountPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        if (position == ME_TAB) {
            if (Utility.isEmpty(fragmentProfile)) {
                fragmentProfile = FragmentFake.create(new FragmentUserProfile(), 50);
            }
            return fragmentProfile;
        } else if (position == BOOKINGS_TAB) {
            if (Utility.isEmpty(fragmentBooking)) {
                fragmentBooking = FragmentFake.create(new FragmentBookings(), 100);
            }
            return fragmentBooking;
        } else if (position == WALLET_TAB) {
            if (Utility.isEmpty(fragmentWallet)) {
                fragmentWallet = FragmentFake.create(new FragmentWallet(), 150);
            }
            return fragmentWallet;
        } else if (position == LIKES_TAB) {
            if (Utility.isEmpty(fragmentLikes)) {
                fragmentLikes = FragmentFake.create(new FragmentLikes(), 200);
            }
            return fragmentLikes;
        }
        return null;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        switch (position) {
            case ME_TAB:
                return getContext().getString(R.string.me_tab);
            case BOOKINGS_TAB:
                return getContext().getString(R.string.bookings_tab);
            case WALLET_TAB:
                return getContext().getString(R.string.wallet_tab);
            case LIKES_TAB:
                return getContext().getString(R.string.likes_tab);
            default:
                return null;
        }
    }

    @Override
    public int getCount() {
        return 4;
    }
}

FragmentFake:

 public class FragmentFake extends Fragment {

private View root;
Fragment fragment;

public static Fragment create(Fragment frag, int timeMs) {
    FragmentFake fragmentFake = new FragmentFake();
    Bundle bundle = new Bundle();
    fragmentFake.fragment = frag;
    bundle.putInt("time", timeMs);
    fragmentFake.setArguments(bundle);
    return fragmentFake;
}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    root = inflater.inflate(R.layout.layout_fake_fragment, container, false);
    Bundle bundle = getArguments();
    replaceFragment(bundle.getInt("time"));
    return root;
}

private void replaceFragment(int time) {
    root.postDelayed(new Runnable() {
        @Override
        public void run() {
            if(!isAdded()){
                return;
            }
            getChildFragmentManager().beginTransaction().add(R.id.replace_fragment_container, fragment).commit();
        }
    }, time);
}

}

报告的错误日志在

     getChildFragmentManager().beginTransaction().add(R.id.replace_fragment_container, fragment).commit();

2 个答案:

答案 0 :(得分:1)

创建一个扩展Fragment的Abstract Fragment。像这样

    public abstract BaseChildFragment extends Fragment{ 
  public void onViewPagerPagechange(); 

}

Make All ChildFragment扩展BaseChildFragment(FragmentUserProfile,FragmentUserLike,FragmentUserWellet,ETC),
在您的适配器上添加以下代码。

LruCache<Integer,BaseChildFragment> cache = new LruCache<>(4);
public BaseChildFragment getBaseChildFragment(int position){
   return cache.get(position);
}

 @Override
public Fragment getItem(int position) {
    if (position == ME_TAB) {
        if (Utility.isEmpty(fragmentProfile)) {
            fragmentProfile = FragmentFake.create(new FragmentUserProfile(), 50);
            cache.put(position,fragmentProfile );
        }
        return fragmentProfile;
    } else if (position == BOOKINGS_TAB) {
        if (Utility.isEmpty(fragmentBooking)) {
            fragmentBooking = FragmentFake.create(new FragmentBookings(), 100);
cache.put(position,fragmentBooking );
        }
        return fragmentBooking;
    } else if (position == WALLET_TAB) {
        if (Utility.isEmpty(fragmentWallet)) {
            fragmentWallet = FragmentFake.create(new FragmentWallet(), 150); 
            cache.put(position,fragmentWallet );
        }
        return fragmentWallet;
    } else if (position == LIKES_TAB) {
        if (Utility.isEmpty(fragmentLikes)) {
            fragmentLikes = FragmentFake.create(new FragmentLikes(), 200);
          cache.put(position,fragmentLikes );
        }
        return fragmentLikes;
    }
    return null;
}

在你的片段中有View浏览器AddpageChangeListener,就像这样

viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {

// optional 
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { }

// optional 
@Override
public void onPageSelected(int position) {
 BaseChildFragment fragment =   adapter.getBaseChildFragment(position);
fragmeng.onViewPagerPagechange(); 
 }
    // optional 
    @Override
    public void onPageScrollStateChanged(int state) { }

});

这将调用您的ChildFragment onViewPagerPagechange();方法。您可以在哪里加载您的子片段。

答案 1 :(得分:0)

你不能这样做

public static Fragment create(Fragment frag, int timeMs) {
    FragmentFake fragmentFake = new FragmentFake();
    Bundle bundle = new Bundle();
    //remove this line, it won't work
    fragmentFake.fragment = frag;
    bundle.putInt("time", timeMs);
    fragmentFake.setArguments(bundle);
    return fragmentFake;
}

您可以从create语句中删除该赋值行,并在创建实例后添加另一种方法来分配该片段。你的代码应该是这样的

    public static Fragment create(Fragment frag, int timeMs) {
    FragmentFake fragmentFake = new FragmentFake();
    Bundle bundle = new Bundle();
    bundle.putInt("time", timeMs);
    fragmentFake.setArguments(bundle);
    return fragmentFake;
}

public void setFragment(Fragment fragment){
    this.fragment = fragment;
}

//How you assign fragment 
FragmentFake fakeFragment = FragmentFake.create(0);
fakeFragment.setFragment(yourFragment);

然后进行片段交易