基于片段的ViewPager作为RecyclerView项生成Null对象引用

时间:2017-08-23 12:27:36

标签: java android android-fragments android-recyclerview android-viewpager

我已将基于Fragment的ViewPager指定为RecyclerView项目。 onBindViewHolder()

中的 RecyclerView.Adapter

生成

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference

使用setText()设置文字时

。表示在绑定值时不创建视图。

我无法弄明白 - >为什么未创建视图,即使在ViewPager中处理FragmentonCreateViewHolder()通货膨胀?我也在onBindViewHolder()尝试了通货膨胀,但仍然是一样。

如何在Page Fragment之前强制onBindViewHolder()充气。

RecyclerView.Adapter

public class MainListRVA extends RecyclerView.Adapter<ViewHolder> implements ConstantValues {

    FragmentManager oFm;

    private int viewPagerId = 1;

    private static ArrayList<MainListItem> oListItems = new ArrayList<MainListItem>();

    MainListRVA(ArrayList<MainListItem> theArray, FragmentManager fm){
        oListItems = theArray;
        oFm = fm;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_pager_main_list_item_folder, parent, false);
        return new FolderVH(v);
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {

        FolderVH folderVH = (FolderVH) holder;
        MainListItem listItem = oListItems.get(position);

        folderVH.fragmentOne.title.setText(listItem.oTitle);
        folderVH.fragmentTwo.title.setText(listItem.oDetail);
        /////////////////////////////////////////////////////
        ////////////////////THIS GIVE NULL POINTER EXCEPTION
    }

    public class FolderVH extends ViewHolder {

        FolderMainPageFragment fragmentOne, fragmentTwo;
        ViewPager viewPager;

        FolderVH(View v) {

            super(v);

            ArrayList<Fragment> fragments = new ArrayList<Fragment>();

            fragmentOne = FolderMainPageFragment.newInstance("one");
            fragmentTwo = FolderMainPageFragment.newInstance("two");

            fragments.add(fragmentOne);
            fragments.add(fragmentTwo);

            FolderVPAdapter folderVPAdapter = new FolderVPAdapter(oFm, fragments);

            viewPager = (ViewPager) v.findViewById(R.id.viewPager);
            viewPager.setId(viewPagerId++);
            viewPager.setAdapter(folderVPAdapter);
        }
    }

    @Override
    public int getItemCount() {
        return oListItems.size();
    }

    void move(int fromPos, int toPos){ }

    void remove(int position){ }
}

FragmentPagerAdapter

public class FolderVPAdapter extends FragmentPagerAdapter {

    private List<Fragment> fragments;

    public FolderVPAdapter(FragmentManager fm, List<Fragment> fragments) {
        super(fm);
        this.fragments = fragments;
    }

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

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

寻呼机片段

public class FolderMainPageFragment extends Fragment {

    TextView title;

    public static FolderMainPageFragment newInstance(String text) {
        return new FolderMainPageFragment();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.main_list_item_view, container, false);
        this.title = (TextView) v.findViewById(R.id.list_title);
        return v;
    }
}

3 个答案:

答案 0 :(得分:1)

这是我的最终解决方案。

1)我添加了一个条件来检查onBindViewHolder

中绑定时视图是否为空

2)如果为null,我只是在片段类中将boolean bindExceptionally标记为true。

3)当片段将在onCreateView()创建视图时,它将检查标志是否为true以设置文本。否则,它将在不设置文本的情况下继续前进。

注意:片段在onCreateViewHolder()而不在onBindViewHolder()中膨胀,因此片段只会膨胀一次然后再循环。

更新 - RecyclerView.Adapter

public class MainListRVA extends RecyclerView.Adapter<ViewHolder> implements ConstantValues {

    FragmentManager oFm;

    private int viewPagerId = 1;

    static ArrayList<MainListItem> oListItems = new ArrayList<MainListItem>();

    MainListRVA(ArrayList<MainListItem> theArray, FragmentManager fm){
        oListItems = theArray;
        oFm = fm;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_pager_main_list_item_folder, parent, false);
        return new FolderVH(v);
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {

        Log.e("onBindViewHolder", "onBindViewHolder");

        FolderVH folderVH = (FolderVH) holder;
        MainListItem listItem = oListItems.get(position);
        folderVH.viewPager.setCurrentItem(0);

        if(folderVH.fragmentOne.title != null) {
            folderVH.fragmentOne.title.setText(listItem.oTitle);
        } else {
            folderVH.fragmentOne.bindExceptionally = true;
            folderVH.fragmentOne.currListItem = listItem;
        }
    }

    public class FolderVH extends RecyclerView.ViewHolder {

        FolderMainPageFragment fragmentOne, fragmentTwo;
        ViewPager viewPager;

        FolderVH(View v) {

            super(v);

            Log.e("FolderVH", "FolderVH");

            ArrayList<Fragment> fragments = new ArrayList<Fragment>();

            fragmentOne = FolderMainPageFragment.newInstance("one");
            fragmentTwo = FolderMainPageFragment.newInstance("two");

            fragments.add(fragmentOne);
            fragments.add(fragmentTwo);

            FolderVPAdapter folderVPAdapter = new FolderVPAdapter(oFm, fragments);

            viewPager = (ViewPager) v.findViewById(R.id.viewPager);
            viewPager.setId(viewPagerId++);
            viewPager.setAdapter(folderVPAdapter);
        }
    }

    @Override
    public int getItemCount() {
        return oListItems.size();
    }

    void move(int fromPos, int toPos){ }

    void remove(int position){ }
}

已更新 - 寻呼机片段

public static class FolderMainPageFragment extends Fragment {

    TextView title;
    boolean bindExceptionally = false;
    MainListItem currListItem;

    public static FolderMainPageFragment newInstance(String text) {
        return new FolderMainPageFragment();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.main_list_item_view_folder, container, false);
        this.title = (TextView) v.findViewById(R.id.list_title);

        if(bindExceptionally) {
            title.setText(currListItem.oTitle);
            bindExceptionally = false;
            currListItem = null;
        }

        return v;
    }
}

答案 1 :(得分:0)

当然title为空。

FolderMainPageFragment在您访问title时甚至还没有开始其生命周期。这意味着onCreateView尚未调用,布局未被夸大,因此title

onCreateViewHolder()中的通货膨胀而言,您只是夸大了布局view_pager_main_list_item_folder而不是main_list_item_view(来自包含FolderMainPageFragment的{​​{1}}),因为title还没有开始。

另外,为什么要将FolderVPAdapter置于ViewPager内?也许你可以做别的事。

要将数据传递给RecyclerView,请在Fragment中写一个方法 handleArgs()

FolderMainPageFragment

编写自己的public class FolderMainPageFragment extends Fragment { TextView title; Bundle mBundle; public void handleArgs(Bundle bundle) { mBundle = bundle; if (title != null) title.setText(bundle.getString("title")); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.main_list_item_view, container, false); this.title = (TextView) v.findViewById(R.id.list_title); if (mBundle != null) // When handleArgs() is called before onCreateView(). handleArgs(mBundle); return v; } } 方法的好处是,您现在可以在 onBindViewHolder()中使用它。但是,您需要想出一种方法,即不在 onBindViewHolder()中创建Bundle的新实例。

答案 2 :(得分:0)

正如阿巴斯所提到的,片段内的观点并非在调用onBindViewHolder时启动。

您应该阅读一些有关片段的内容,如果片段是您想要的方式,那么您应该将片段内特定片段的视图逻辑分开。 您应该传递给片段的唯一信息是您在片段启动时使用setArguments传递的束中的信息。有很多生命周期问题会给你带来痛苦。

在这种情况下,如果你想为片段设置标题,你应该在开始时做这样的事情:

Bundle args = new Bundle();
bundle.putString("title", "My title");
fragmentOne = FolderMainPageFragment.newInstance("one");
fragmentOne.setArguments(args);

然后在你的片段中onViewCreated()

Bundle args = getArguments();
title.setText(args.getString("title"));