繼承 ListFragment 並在 onCreate() 中直接呼叫 setListAdapter(),編譯報錯「Cannot resolve method」。
ListFragment 的 setListAdapter() 依賴內部 ListView 已建立完成。ListView 在 Fragment 的 onCreateView() 才會被建立(或使用預設佈局),因此必須在 視圖建立後 才能設定 Adapter。
public class CrimeListFragment extends ListFragment {
private ArrayList mCrimes;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setTitle(R.string.crimes_title);
mCrimes = CrimeLab.get(getActivity()).getCrimes();
// ❌ 這裡呼叫 setListAdapter() 會失敗,ListView 尚未建立
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// ✅ 正確位置:Activity 的 onCreate() 完成,Fragment 視圖已建立
ArrayAdapter adapter = new ArrayAdapter<>(
getActivity(),
android.R.layout.simple_list_item_1,
mCrimes
);
setListAdapter(adapter);
}
}
| 方法 | 視圖狀態 | 可呼叫 setListAdapter |
|---|---|---|
onCreate() | 未建立 | ❌ |
onCreateView() | 建立中(返回 View) | ❌ (ListView 可能尚未 attach) |
onViewCreated() | 已建立 | ✅ (API 17+ 推薦) |
onActivityCreated() | 已建立並附著 | ✅ (傳統寫法、相容性最好) |
ListFragment 已被標記為 Deprecated (API 28+)。新專案請直接使用 Fragment + RecyclerView + ViewBinding:
public class CrimeListFragment extends Fragment {
private FragmentCrimeListBinding binding;
private CrimeAdapter adapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
binding = FragmentCrimeListBinding.inflate(inflater, container, false);
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
adapter = new CrimeAdapter(CrimeLab.get(requireContext()).getCrimes());
binding.recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
binding.recyclerView.setAdapter(adapter);
}
}
若維護舊專案必須用 ListFragment,請務必在 onActivityCreated() 或 onViewCreated() 設定 Adapter,切勿在 onCreate()。