TabLayout切换时RecyclerView内容刷新异常问题排查
Tab切换回第一个Tab时RecyclerView内容不更新的问题修复
我仔细看了你的代码,很快就找到了导致问题的核心原因,还有几个可以优化的点,一起来解决:
核心问题:Switch Case缺少Break语句
你的TabLayout选中监听里的switch代码块,case 0后面没有添加break!这会导致选中第一个Tab(position=0)时,代码执行完refreshList("/sdcard/")后,会继续往下执行case 1的refreshList("/storage/0000-0000/")——相当于最后还是加载了第二个Tab的路径内容,所以你看起来第一个Tab的内容没变化,实际上是被后续代码覆盖了。
修复后的Tab监听代码
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { System.out.println(tab.getPosition()); switch(tab.getPosition()){ case 0: refreshList("/sdcard/"); break; // 必须添加这个break,终止当前case的执行 case 1: refreshList("/storage/0000-0000/"); break; // 这里也建议加上,养成良好编码习惯 } } @Override public void onTabUnselected(TabLayout.Tab tab) {} @Override public void onTabReselected(TabLayout.Tab tab) {} });
额外优化建议(提升代码稳定性与性能)
1. 处理权限申请后的回调
你现在申请了存储权限,但没有处理权限申请结果的回调。当用户授予权限后,需要重新调用refreshList,否则第一次打开App如果用户刚授权,列表不会加载。在Fragment中添加以下代码:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == MY_PERMISSIONS_REQUEST_EXTERNAL_STORAGE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 权限授予成功,刷新当前选中Tab的列表 TabLayout.Tab selectedTab = tabLayout.getSelectedTab(); if (selectedTab != null) { switch(selectedTab.getPosition()){ case 0: refreshList("/sdcard/"); break; case 1: refreshList("/storage/0000-0000/"); break; } } } else { // 提示用户需要权限才能查看文件 Snackbar.make(view, "需要存储权限才能访问文件", Snackbar.LENGTH_LONG).show(); } } }
2. 复用RecyclerView Adapter,避免频繁创建实例
每次调用refreshList都创建新的OwnAdapter实例会浪费资源,建议复用已有Adapter,更新数据集后通知刷新:
修改OwnAdapter,添加数据更新方法
public class OwnAdapter extends RecyclerView.Adapter<OwnAdapter.MyViewHolder> { private String[] dataset; public static class MyViewHolder extends RecyclerView.ViewHolder { public TextView textView; public MyViewHolder(TextView v) { super(v); textView = v; } } public OwnAdapter(String[] myDataset) { dataset = myDataset; } // 添加更新数据集的方法 public void updateData(String[] newDataset) { dataset = newDataset; notifyDataSetChanged(); } @NonNull @Override public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { TextView v = (TextView) LayoutInflater.from(parent.getContext()) .inflate(R.layout.textview_for_files, parent, false); return new MyViewHolder(v); } @Override public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { holder.textView.setText(dataset[position]); } @Override public int getItemCount() { return dataset.length; } }
修改refreshList方法,复用Adapter
private void refreshList(String s){ File file = new File(s); File[] files = file.listFiles(); ArrayList<File> itemArrayList = new ArrayList<>(); // 防止files为null导致空指针异常 if (files != null) { for (File f : files) { itemArrayList.add(f.isFile() ? f : f.getAbsoluteFile()); } } String[] itemNames = new String[itemArrayList.size()]; for(int j = 0; j < itemNames.length; j++){ itemNames[j] = itemArrayList.get(j).getName(); } if (ownAdapter == null) { ownAdapter = new OwnAdapter(itemNames); recView.setAdapter(ownAdapter); } else { ownAdapter.updateData(itemNames); } }
3. 空指针防护
file.listFiles()可能返回null(比如路径不存在、权限不足),所以一定要先判断files != null再遍历,避免抛出RuntimeException。
内容的提问来源于stack exchange,提问作者user11598413
相关产品推荐
相关产品推荐

