ViewPager中Fragment可见时执行操作及跨Fragment获取SQLite数据的方法
我来帮你解决这两个ViewPager相关的问题,都是日常开发中很常见的场景:
根据你使用的ViewPager版本,有几种可靠的实现方式:
使用
setUserVisibleHint(适配旧版ViewPager)
这个方法是旧版ViewPager中判断Fragment可见性的经典方式,重写它就能在可见状态变化时触发操作:@Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); // 加上isResumed()判断,避免Fragment未初始化完成就执行操作 if (isVisibleToUser && isResumed()) { // 这里写你需要执行的操作 performVisibleAction(); } }使用ViewPager2的
OnPageChangeCallback(推荐,适配ViewPager2)
如果你用的是更现代的ViewPager2,可以在宿主Activity/Fragment中监听页面切换,主动通知目标Fragment:viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { @Override public void onPageSelected(int position) { super.onPageSelected(position); // 根据tag获取当前选中的Fragment(注意tag的命名要和Adapter中一致) YourTargetFragment currentFragment = (YourTargetFragment) getSupportFragmentManager() .findFragmentByTag("android:switcher:" + viewPager2.getId() + ":" + position); if (currentFragment != null) { currentFragment.onFragmentBecomeVisible(); } } });然后在Fragment中定义对应的方法:
public void onFragmentBecomeVisible() { // 执行可见时的操作 }通过
setMaxLifecycle控制生命周期(精准控制)
这种方式可以让只有当前可见的Fragment处于RESUMED状态,其他处于STARTED,这样你就能直接在onResume()中执行操作:// 在ViewPager的Adapter中重写setPrimaryItem @Override public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) { super.setPrimaryItem(container, position, object); if (object instanceof Fragment) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); // 当前页面Fragment设置为RESUMED transaction.setMaxLifecycle((Fragment) object, Lifecycle.State.RESUMED); // 其他Fragment设置为STARTED for (Fragment fragment : getSupportFragmentManager().getFragments()) { if (fragment != object && fragment.isAdded()) { transaction.setMaxLifecycle(fragment, Lifecycle.State.STARTED); } } transaction.commitNow(); } }之后在Fragment的
onResume()中写操作即可:@Override public void onResume() { super.onResume(); // 只有Fragment可见时才会调用这里 doVisibleTask(); }
针对你的场景,有几种实用的方案,推荐按优先级选择:
直接在目标Fragment中查询数据库(最可靠)
这是最推荐的方式,每个Fragment独立获取数据,避免数据传递带来的不一致问题,也符合模块化设计:// 在目标Fragment的onViewCreated中执行查询 private HashMap<String,String> prefernceHashMap; @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); try { dbOperation.open(); prefernceHashMap = dbOperation.getPreference(); // 获取数据后执行后续逻辑 } catch(Exception e) { e.printStackTrace(); } finally { dbOperation.close(); } }使用Bundle传递数据(适合简单场景)
如果数据不需要实时更新,可以用Bundle把已查询到的数据传递给下一个Fragment,这是Android官方推荐的Fragment数据传递方式:// 在当前Fragment中打包数据 Bundle bundle = new Bundle(); // HashMap实现了Serializable接口,可以直接存入 bundle.putSerializable("PREFERENCE_MAP", prefernceHashMap); NextFragment nextFragment = new NextFragment(); nextFragment.setArguments(bundle); // 在NextFragment中获取数据 @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { prefernceHashMap = (HashMap<String, String>) getArguments().getSerializable("PREFERENCE_MAP"); // 处理数据 } }使用ViewModel共享数据(适合复杂交互场景)
如果多个Fragment需要共享数据且需要实时同步,ViewModel是最佳选择,它能在配置变化(如屏幕旋转)时保留数据:// 定义共享ViewModel public class SharedPreferenceViewModel extends ViewModel { private final MutableLiveData<HashMap<String, String>> preferenceLiveData = new MutableLiveData<>(); public void updatePreferenceData(HashMap<String, String> data) { preferenceLiveData.setValue(data); } public LiveData<HashMap<String, String>> getPreferenceData() { return preferenceLiveData; } } // 在当前Fragment中设置数据 SharedPreferenceViewModel viewModel = new ViewModelProvider(requireActivity()).get(SharedPreferenceViewModel.class); viewModel.updatePreferenceData(prefernceHashMap); // 在目标Fragment中观察数据变化 SharedPreferenceViewModel viewModel = new ViewModelProvider(requireActivity()).get(SharedPreferenceViewModel.class); viewModel.getPreferenceData().observe(getViewLifecycleOwner(), data -> { if (data != null) { prefernceHashMap = data; // 数据更新后的操作 } });
内容的提问来源于stack exchange,提问作者Vikas Semwal

