切换主题后Adapter为空,调用addTask时应用崩溃的修复咨询
问题修复:切换主题后Adapter为空导致崩溃
问题根源
切换深色/浅色主题会触发Activity重建,Fragment也会随之销毁并重新创建。如果你的代码中是通过旧的Fragment实例调用addTask,这个旧实例的adapter在重建后并未被重新初始化(旧实例已不再关联新的View),同时原代码中arrTask存在未初始化的风险,最终导致调用addTask时adapter为空,引发崩溃。
修复方案
1. 确保数据列表始终初始化
避免arrTask为null,在Fragment构造和数据恢复阶段都保证列表不为空:
public class ToDoFragment extends Fragment { Context context; LinearLayout no_tasks; RecyclerView tasks_list; ToDoRecyclerAdapter adapter; ArrayList<Task_Model> arrTask; // Fragment重建必须调用无参构造,提前初始化空列表 public ToDoFragment(){ arrTask = new ArrayList<>(); } public ToDoFragment(ArrayList<Task_Model> arrTask){ // 传入列表为空时自动初始化空列表 this.arrTask = arrTask != null ? arrTask : new ArrayList<>(); }
2. 优化View创建与Adapter初始化逻辑
在onCreateView中确保adapter始终被正确初始化,同时使用Activity上下文而非Application上下文:
@Override @SuppressWarnings("unchecked") public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_to_do, container, false); tasks_list = rootView.findViewById(R.id.tasks_list); no_tasks = rootView.findViewById(R.id.no_tasks); context = requireActivity(); // 使用Activity上下文更适配UI操作 tasks_list.setLayoutManager(new LinearLayoutManager(context)); if (savedInstanceState != null) { ArrayList<Task_Model> savedTasks = (ArrayList<Task_Model>) savedInstanceState.getSerializable("tasks"); // 恢复数据时同样避免null arrTask = savedTasks != null ? savedTasks : new ArrayList<>(); } // 确保adapter始终被初始化,arrTask不会为null adapter = new ToDoRecyclerAdapter(arrTask); tasks_list.setAdapter(adapter); updateNoTasksVisibility(); return rootView; }
3. 增强addTask方法的容错性
即使adapter为空,也要保证数据正确同步,并重新创建关联adapter:
public void addTask(String task_name, String task_desc, char priority){ arrTask.add(new Task_Model(task_name, task_desc, priority)); updateNoTasksVisibility(); // 双重检查adapter有效性,失效则重新创建 if (adapter != null && tasks_list.getAdapter() == adapter) { adapter.notifyItemInserted(arrTask.size() - 1); } else { adapter = new ToDoRecyclerAdapter(arrTask); tasks_list.setAdapter(adapter); } } // 提取重复的UI更新逻辑 private void updateNoTasksVisibility(){ no_tasks.setVisibility(tasksPresent() ? View.INVISIBLE : View.VISIBLE); }
4. 调用addTask时使用当前活跃的Fragment实例
避免持有旧Fragment的引用,每次调用都从FragmentManager获取当前实例:
// 在Activity中调用addTask的正确方式 ToDoFragment currentFragment = (ToDoFragment) getSupportFragmentManager() .findFragmentById(R.id.your_fragment_container_id); if (currentFragment != null) { currentFragment.addTask("新任务", "任务描述", 'H'); }
核心修复点
- 保证
arrTask永远不为null,从根源避免空指针 addTask方法增加容错逻辑,adapter失效时自动重建- 调用方法时获取当前活跃的Fragment实例,避免操作旧实例
内容的提问来源于stack exchange,提问作者Shubham Dagar
相关产品推荐
相关产品推荐

