RecyclerView: No adapter attached; skipping layout
Fragment 切換離開又回來時(如 ViewPager、BottomNavigationView),onCreateView 會重新執行,**但 RecyclerView 實例可能被保留**(取決於 setOffscreenPageLimit 或父容器)。若在 onResume/onViewCreated 再次呼叫 recyclerView = view.findViewById(...) 卻**忘記重新 setAdapter**,或將 recyclerView 設為 null 後未重設,即會出現此警告。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_list, container, false);
recyclerView = view.findViewById(R.id.rv); // 每次都新找
return view;
}
@Override
public void onResume() {
super.onResume();
// 錯誤:這裡重新初始化 LayoutManager 但沒有 setAdapter
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
// 缺少 recyclerView.setAdapter(adapter);
}
private RecyclerView recyclerView;
private MyAdapter adapter;
private List<Item> dataList = new ArrayList<>();
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_list, container, false);
recyclerView = view.findViewById(R.id.rv);
recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
// Adapter 只建立一次,複用
if (adapter == null) {
adapter = new MyAdapter(dataList);
recyclerView.setAdapter(adapter);
}
return view;
}
@Override
public void onResume() {
super.onResume();
// 只負責更新資料,不重設 LayoutManager/Adapter
loadData(); // 內部做 dataList.clear(); dataList.addAll(...); adapter.notifyDataSetChanged();
}
private FragmentListBinding binding;
private MyAdapter adapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
binding = FragmentListBinding.inflate(inflater, container, false);
binding.rv.setLayoutManager(new LinearLayoutManager(requireContext()));
adapter = new MyAdapter();
binding.rv.setAdapter(adapter);
return binding.getRoot();
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null; // 釋放 View 參考,防洩漏
}
setLayoutManager 只在 onCreateView 呼叫一次。setAdapter 只在 onCreateView 呼叫一次(或 adapter == null 時)。onResume/onStart **只更新資料並 notifyDataSetChanged()**。DiffUtil / ListAdapter 取代手動 notify,效能更好。「No adapter attached」源於 **Fragment 重建 View 時重設 LayoutManager 卻漏設 Adapter**。遵循「View 初始化一次、資料更新多次」原則,將 setAdapter 放入 onCreateView 並配合 adapter == null 守衛即可徹底解決。