You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android底部导航切换至SAVED项后卡顿无法切换其他菜单

Android底部导航栏切换至SAVED项后卡顿无法切换问题

我的Android应用底部导航栏包含HOME、APPLICATIONS、SAVED、INFO四个菜单项,其中HOME、APPLICATIONS和INFO项切换正常,但切换至SAVED项后,底部导航栏出现卡顿,无法再切换到其他菜单项。

相关代码

SavedFragment

public class SavedFragment extends Fragment {
private FragmentSavedBinding binding;

public View onCreateView(@NonNull LayoutInflater inflater,
                         ViewGroup container, Bundle savedInstanceState) {
    binding = FragmentSavedBinding.inflate(inflater, container, false);
    View root = binding.getRoot();
    ListView fileNameList = root.findViewById(R.id.listViewFiles);

    ArrayList<String> filenames = new ArrayList<>();

    File directory = new File(getActivity().getExternalFilesDir(null), "");
    File[] files = directory.listFiles((dir, name) -> name.toLowerCase().endsWith(".xls"));

    for (int i = 0; i < files.length; i++)
    {

        String file_name = files[i].getName();

        filenames.add(file_name);
    }
    ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, filenames);

    fileNameList.setAdapter(arrayAdapter);
    
    
    return root;

}

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    // TODO: Use the ViewModel
}
}

MainActivity

public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    binding = ActivityMainBinding.inflate(getLayoutInflater());
    setContentView(binding.getRoot());
    BottomNavigationView navView = findViewById(R.id.nav_view);
    AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
            R.id.navigation_home, R.id.navigation_applications, R.id.navigation_saved, R.id.navigation_info)
            .build();
    NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);
    NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
    NavigationUI.setupWithNavController(binding.navView, navController);
}
}

bottom_nav_menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android">

<item
    android:id="@+id/navigation_home"
    android:icon="@drawable/ic_home_black_24dp"
    android:title="@string/title_home" />

<item
    android:id="@+id/navigation_applications"
    android:icon="@drawable/ic_dashboard_black_24dp"
    android:title="@string/title_applications" />

<item
    android:id="@+id/placeholder"
    android:title="" />

<item
    android:id="@+id/navigation_saved"
    android:icon="@drawable/baseline_save_alt_24"
    android:title="@string/title_saved" />

<item
    android:id="@+id/navigation_info"
    android:icon="@drawable/baseline_info_24"
    android:title="@string/title_info" />

</menu>

mobile_navigation.xml

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mobile_navigation"
app:startDestination="@+id/navigation_home">

<fragment
    android:id="@+id/navigation_home"
    android:name="com.cremcash.eloan.ui.home.HomeFragment"
    android:label="@string/title_home"
    tools:layout="@layout/fragment_home" />

<fragment
    android:id="@+id/navigation_applications"
    android:name="com.cremcash.eloan.ui.applications.ApplicationsFragment"
    android:label="@string/title_applications"
    tools:layout="@layout/fragment_applications" />

<fragment
    android:id="@+id/navigation_saved"
    android:name="com.cremcash.eloan.ui.saved.SavedFragment"
    android:label="@string/title_saved"
    tools:layout="@layout/fragment_saved" />

<fragment
    android:id="@+id/navigation_info"
    android:name="com.cremcash.eloan.ui.info.InfoFragment"
    android:label="@string/logout"
    tools:layout="@layout/fragment_info" />
</navigation>

问题原因

  1. 主线程执行耗时IO操作:SavedFragment的onCreateView中直接进行文件目录遍历和读取操作,这是耗时的IO任务,会阻塞主线程,导致UI卡顿,底部导航栏的点击事件无法被及时处理。
  2. 空指针隐患:directory.listFiles()可能返回null(如目录不存在、无读取权限),此时直接访问files.length会触发空指针异常,导致Fragment加载失败,进而影响导航功能。

解决方案

1. 将文件操作移至后台线程

使用AsyncTask将文件读取任务放到子线程执行,避免阻塞主线程:

public class SavedFragment extends Fragment {
    private FragmentSavedBinding binding;
    private ArrayAdapter<String> arrayAdapter;
    private ArrayList<String> filenames = new ArrayList<>();

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        binding = FragmentSavedBinding.inflate(inflater, container, false);
        View root = binding.getRoot();
        ListView fileNameList = root.findViewById(R.id.listViewFiles);

        arrayAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, filenames);
        fileNameList.setAdapter(arrayAdapter);

        // 启动异步任务加载文件列表
        new LoadFilesTask().execute();

        return root;
    }

    private class LoadFilesTask extends AsyncTask<Void, Void, ArrayList<String>> {
        @Override
        protected ArrayList<String> doInBackground(Void... voids) {
            ArrayList<String> result = new ArrayList<>();
            File directory = new File(getActivity().getExternalFilesDir(null), "");
            // 先判断目录是否存在且为目录
            if (directory.exists() && directory.isDirectory()) {
                File[] files = directory.listFiles((dir, name) -> name.toLowerCase().endsWith(".xls"));
                // 处理listFiles返回null的情况
                if (files != null) {
                    for (File file : files) {
                        result.add(file.getName());
                    }
                }
            }
            return result;
        }

        @Override
        protected void onPostExecute(ArrayList<String> result) {
            filenames.clear();
            filenames.addAll(result);
            arrayAdapter.notifyDataSetChanged();
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }
}

2. 优化占位菜单项(可选)

底部导航菜单中的placeholder项如果仅用于布局对称,建议禁用并隐藏,避免干扰导航逻辑:

<item
    android:id="@+id/placeholder"
    android:title=""
    android:enabled="false"
    android:visible="false"/>

内容的提问来源于stack exchange,提问作者JeffyO

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 00:45:56