如何从 viewpager2 访问 RecyclerView?
How to access RecyclerViews from view pager2?
已创建 tabLayout 和 pager2
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
myFragment = inflater.inflate(R.layout.fragment_home, container, false);
tabLayout = myFragment.findViewById(R.id.tab_layout);
pager2 = myFragment.findViewById(R.id.view_pager2);
Button calculate = myFragment.findViewById(R.id.calculate_button);
FragmentManager fm = getFragmentManager();
adapter = new FragmentAdapterRecycler(fm, getLifecycle());
pager2.setAdapter(adapter);
位于onCreateView中:如果页面滑动,那么RecyclerView在调用fillFragement()时会正常填充如果是先点击tab,那么RecyclerView在fillFragment()中会导致程序崩溃,因为java.lang.NullPointerException:
pager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
calc = (TextView) myFragment.findViewById(R.id.numDisplay);
fillFragment(pager2.getCurrentItem());
tabLayout.selectTab(tabLayout.getTabAt(position));
}
});
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
pager2.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) { }
@Override
public void onTabReselected(TabLayout.Tab tab) { }
});
fillFragment() 这会定位 RecyclerView 并根据所选页面填充它。每个页面都有自己的 RecyclerView。
public void fillFragment(int position) {
if (position == 0 && isChosen) {
String iterations = "Total Iterations: " + collatz.getIterationTotal();
calc.setText(iterations);
if (tabLoaded1 == false) {
mRecyclerView = (RecyclerView) getView().findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(false);
mLayoutManager = new LinearLayoutManager(getActivity());
mAdapter = new CollatzAdapter(collatz.getCollatzList());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
tabLoaded1 = true;
}
}
if (position == 1 && isChosen) {
String evenTotal = "Total Even: " + collatz.getEvenTotal();
calc.setText(evenTotal);
if (tabLoaded2 == false) {
mRecyclerView = (RecyclerView) myFragment.findViewById(R.id.recycler_view_even);
mRecyclerView.setHasFixedSize(false);
mLayoutManager = new LinearLayoutManager(getActivity());
mAdapter = new CollatzAdapter(collatz.getEvenList());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
tabLoaded2 = true;
}
}
if (position == 2 && isChosen) {
String oddTotal = "Total Odd: " + collatz.getOddTotal();
calc.setText(oddTotal);
if (tabLoaded3 == false) {
mRecyclerView = (RecyclerView) myFragment.findViewById(R.id.recycler_view_odd);
mRecyclerView.setHasFixedSize(false);
mLayoutManager = new LinearLayoutManager(getActivity());
mAdapter = new CollatzAdapter(collatz.getOddList());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
tabLoaded3 = true;
}
}
}
总而言之,在调用 fillFragment() 时单击选项卡会导致空对象引用。滑动页面时它工作正常。这是因为单击选项卡时,会先调用 fillFragment(),然后再创建 Pager2 项目。滑动时,先创建Pager2 item,再调用fillFragment(),即先创建RecyclerView,再访问
如果 pageView 总是在我填充后创建,导致空对象引用,我如何在单击选项卡时填充 RecyclerView?
StackTrace
您可以通过对当前解决方案进行少量更改来解决此问题。但我建议你重新考虑什么对什么负责。
因为片段遵循它们自己的生命周期,所以您不能保证在任何给定时间附加片段。
因此,当您从可能“存在”或可能不“存在”的片段中提取 RecyclerViews 时,您将得到 null。
碎片应该对自己的观点完全负责,任何其他实体都不应触及它们。
最好的解决方案是拥有一个所有 4 个片段都可以访问的 SharedViewModel。
// in evenFragment
CollatzViewModel collatzViewModel;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
collatzViewModel = new ViewModelProviders(getActivity()).get(CollatzViewModel.class);
evenFragment = inflater.inflate(R.layout.fragment_even, container, false);
mRecyclerView = (RecyclerView) evenFragment .findViewById(R.id.recycler_view_even);
mRecyclerView.setHasFixedSize(false);
mLayoutManager = new LinearLayoutManager(getActivity());
mAdapter = new CollatzAdapter();
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
collatzViewModel.getCollatz().observe(getViewLifeCycle(),(list)->{
mAdapter.setList(list);
mAdapter.notifyDataSetChanged();
});
return evenFragment;
}
//in odd fragment
CollatzViewModel collatzViewModel;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
collatzViewModel = new ViewModelProviders(getActivity()).get(CollatzViewModel.class);
oddFragment = inflater.inflate(R.layout.fragment_odd, container, false);
mRecyclerView = (RecyclerView) oddFragment.findViewById(R.id.recycler_view_odd);
mRecyclerView.setHasFixedSize(false);
mLayoutManager = new LinearLayoutManager(getActivity());
mAdapter = new CollatzAdapter();
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
collatzViewModel.getCollatz().observe(getViewLifeCycle(),(list)->{
mAdapter.setList(list);
mAdapter.notifyDataSetChanged();
});
return oddFragment;
}
//in iteration fragment
CollatzViewModel collatzViewModel;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
iterationFragment = inflater.inflate(R.layout.fragment_iteration, container, false);
collatzViewModel = new ViewModelProviders(getActivity()).get(CollatzViewModel.class);
mRecyclerView = (RecyclerView) iterationFragment.findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(false);
mLayoutManager = new LinearLayoutManager(getActivity());
mAdapter = new CollatzAdapter();
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
collatzViewModel.getCollatz().observe(getViewLifeCycle(),(list)->{
mAdapter.setList(list);
mAdapter.notifyDataSetChanged();
});
return iterationFragment;
}
//ViewModel class
public class CollatzViewModel extends ViewModel{
private MutableLiveData<List<BigInteger>> collatz = new MutableLiveData();
public MutableLiveData<List<BigInteger>> getCollatz(){
return collatz;
}
}
//home fragment
CollatzViewModel collatzViewModel;
public void fillFragment(int position) {
if (position == 0 && isChosen) {
String iterations = "Total Iterations: " + collatz.getIterationTotal();
calc.setText(iterations);
if (tabLoaded1 == false) {
collatzViewModel.getCollatz().setValue(collatz.getCollatzList())
tabLoaded1 = true;
}
}
if (position == 1 && isChosen) {
String evenTotal = "Total Even: " + collatz.getEvenTotal();
calc.setText(evenTotal);
if (tabLoaded2 == false) {
collatzViewModel.getCollatz().setValue(collatz.getEvenList())
tabLoaded2 = true;
}
}
if (position == 2 && isChosen) {
String oddTotal = "Total Odd: " + collatz.getOddTotal();
calc.setText(oddTotal);
if (tabLoaded3 == false) {
collatzViewModel.getCollatz().setValue(collatz.getOddList())
tabLoaded3 = true;
}
}
}
已创建 tabLayout 和 pager2
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
myFragment = inflater.inflate(R.layout.fragment_home, container, false);
tabLayout = myFragment.findViewById(R.id.tab_layout);
pager2 = myFragment.findViewById(R.id.view_pager2);
Button calculate = myFragment.findViewById(R.id.calculate_button);
FragmentManager fm = getFragmentManager();
adapter = new FragmentAdapterRecycler(fm, getLifecycle());
pager2.setAdapter(adapter);
位于onCreateView中:如果页面滑动,那么RecyclerView在调用fillFragement()时会正常填充如果是先点击tab,那么RecyclerView在fillFragment()中会导致程序崩溃,因为java.lang.NullPointerException:
pager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
calc = (TextView) myFragment.findViewById(R.id.numDisplay);
fillFragment(pager2.getCurrentItem());
tabLayout.selectTab(tabLayout.getTabAt(position));
}
});
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
pager2.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) { }
@Override
public void onTabReselected(TabLayout.Tab tab) { }
});
fillFragment() 这会定位 RecyclerView 并根据所选页面填充它。每个页面都有自己的 RecyclerView。
public void fillFragment(int position) {
if (position == 0 && isChosen) {
String iterations = "Total Iterations: " + collatz.getIterationTotal();
calc.setText(iterations);
if (tabLoaded1 == false) {
mRecyclerView = (RecyclerView) getView().findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(false);
mLayoutManager = new LinearLayoutManager(getActivity());
mAdapter = new CollatzAdapter(collatz.getCollatzList());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
tabLoaded1 = true;
}
}
if (position == 1 && isChosen) {
String evenTotal = "Total Even: " + collatz.getEvenTotal();
calc.setText(evenTotal);
if (tabLoaded2 == false) {
mRecyclerView = (RecyclerView) myFragment.findViewById(R.id.recycler_view_even);
mRecyclerView.setHasFixedSize(false);
mLayoutManager = new LinearLayoutManager(getActivity());
mAdapter = new CollatzAdapter(collatz.getEvenList());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
tabLoaded2 = true;
}
}
if (position == 2 && isChosen) {
String oddTotal = "Total Odd: " + collatz.getOddTotal();
calc.setText(oddTotal);
if (tabLoaded3 == false) {
mRecyclerView = (RecyclerView) myFragment.findViewById(R.id.recycler_view_odd);
mRecyclerView.setHasFixedSize(false);
mLayoutManager = new LinearLayoutManager(getActivity());
mAdapter = new CollatzAdapter(collatz.getOddList());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
tabLoaded3 = true;
}
}
}
总而言之,在调用 fillFragment() 时单击选项卡会导致空对象引用。滑动页面时它工作正常。这是因为单击选项卡时,会先调用 fillFragment(),然后再创建 Pager2 项目。滑动时,先创建Pager2 item,再调用fillFragment(),即先创建RecyclerView,再访问
如果 pageView 总是在我填充后创建,导致空对象引用,我如何在单击选项卡时填充 RecyclerView?
StackTrace
您可以通过对当前解决方案进行少量更改来解决此问题。但我建议你重新考虑什么对什么负责。
因为片段遵循它们自己的生命周期,所以您不能保证在任何给定时间附加片段。
因此,当您从可能“存在”或可能不“存在”的片段中提取 RecyclerViews 时,您将得到 null。
碎片应该对自己的观点完全负责,任何其他实体都不应触及它们。
最好的解决方案是拥有一个所有 4 个片段都可以访问的 SharedViewModel。
// in evenFragment
CollatzViewModel collatzViewModel;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
collatzViewModel = new ViewModelProviders(getActivity()).get(CollatzViewModel.class);
evenFragment = inflater.inflate(R.layout.fragment_even, container, false);
mRecyclerView = (RecyclerView) evenFragment .findViewById(R.id.recycler_view_even);
mRecyclerView.setHasFixedSize(false);
mLayoutManager = new LinearLayoutManager(getActivity());
mAdapter = new CollatzAdapter();
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
collatzViewModel.getCollatz().observe(getViewLifeCycle(),(list)->{
mAdapter.setList(list);
mAdapter.notifyDataSetChanged();
});
return evenFragment;
}
//in odd fragment
CollatzViewModel collatzViewModel;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
collatzViewModel = new ViewModelProviders(getActivity()).get(CollatzViewModel.class);
oddFragment = inflater.inflate(R.layout.fragment_odd, container, false);
mRecyclerView = (RecyclerView) oddFragment.findViewById(R.id.recycler_view_odd);
mRecyclerView.setHasFixedSize(false);
mLayoutManager = new LinearLayoutManager(getActivity());
mAdapter = new CollatzAdapter();
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
collatzViewModel.getCollatz().observe(getViewLifeCycle(),(list)->{
mAdapter.setList(list);
mAdapter.notifyDataSetChanged();
});
return oddFragment;
}
//in iteration fragment
CollatzViewModel collatzViewModel;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
iterationFragment = inflater.inflate(R.layout.fragment_iteration, container, false);
collatzViewModel = new ViewModelProviders(getActivity()).get(CollatzViewModel.class);
mRecyclerView = (RecyclerView) iterationFragment.findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(false);
mLayoutManager = new LinearLayoutManager(getActivity());
mAdapter = new CollatzAdapter();
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
collatzViewModel.getCollatz().observe(getViewLifeCycle(),(list)->{
mAdapter.setList(list);
mAdapter.notifyDataSetChanged();
});
return iterationFragment;
}
//ViewModel class
public class CollatzViewModel extends ViewModel{
private MutableLiveData<List<BigInteger>> collatz = new MutableLiveData();
public MutableLiveData<List<BigInteger>> getCollatz(){
return collatz;
}
}
//home fragment
CollatzViewModel collatzViewModel;
public void fillFragment(int position) {
if (position == 0 && isChosen) {
String iterations = "Total Iterations: " + collatz.getIterationTotal();
calc.setText(iterations);
if (tabLoaded1 == false) {
collatzViewModel.getCollatz().setValue(collatz.getCollatzList())
tabLoaded1 = true;
}
}
if (position == 1 && isChosen) {
String evenTotal = "Total Even: " + collatz.getEvenTotal();
calc.setText(evenTotal);
if (tabLoaded2 == false) {
collatzViewModel.getCollatz().setValue(collatz.getEvenList())
tabLoaded2 = true;
}
}
if (position == 2 && isChosen) {
String oddTotal = "Total Odd: " + collatz.getOddTotal();
calc.setText(oddTotal);
if (tabLoaded3 == false) {
collatzViewModel.getCollatz().setValue(collatz.getOddList())
tabLoaded3 = true;
}
}
}