Fragment返回CursorLoader时出现类型不兼容问题求助
嘿,我来帮你搞定这个类型不兼容的报错!你遇到的CursorLoader cannot be converted to Loader问题,核心原因是没有给LoaderManager.LoaderCallbacks指定泛型参数,导致整个回调接口的类型不匹配。
问题根源
你现在的Fragment实现的是原始类型的LoaderManager.LoaderCallbacks,而onCreateLoader返回的是Loader<Cursor>(CursorLoader的父类是Loader<Cursor>)。由于泛型的类型擦除,原始类型的回调会默认把Loader的类型当成Loader<Object>,这时候Loader<Cursor>和Loader<Object>是无法直接转换的,所以编译器就会报错。
具体修复步骤
1. 给LoaderCallbacks指定泛型<Cursor>
修改你的Fragment类声明,把LoaderManager.LoaderCallbacks改成LoaderManager.LoaderCallbacks<Cursor>:
public class InventoryFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> { // 你的其他代码... }
2. 修正onLoadFinished和onLoaderReset的参数类型
这两个方法的参数需要和泛型类型对应,把Loader改成Loader<Cursor>,Object data改成Cursor data:
@Override public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor data) { // 这里把加载完成的Cursor传给Adapter,更新UI mCursorAdapter.swapCursor(data); } @Override public void onLoaderReset(@NonNull Loader<Cursor> loader) { // 重置Loader时清空Adapter的Cursor mCursorAdapter.swapCursor(null); }
3. 额外注意:ListView ID匹配问题
我看到你在代码里用rootView.findViewById(R.id.list_view),但你的activity_main.xml里的ListView ID是@+id/display_view,这会导致ListView找不到而出现空指针异常,记得把代码里的ID改成和布局一致:
ListView listView = rootView.findViewById(R.id.display_view);
修改后的完整InventoryFragment代码示例
public class InventoryFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> { private static final String LOG_TAG = InventoryFragment.class.getName(); //create an integer for the book loader private static final int STOCK_LOADER = 0; PlatformCursorAdapter mCursorAdapter; public InventoryFragment(){} @Override public void onActivityCreated(Bundle savedInstanceState){ getActivity().getSupportLoaderManager().initLoader(STOCK_LOADER, null, this); super.onActivityCreated(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle saveInstanceState){ mCursorAdapter = new PlatformCursorAdapter(getActivity(),null); View rootView = inflater.inflate(R.layout.activity_main, container, false); ListView listView = rootView.findViewById(R.id.display_view); // 修正ID listView.setAdapter(mCursorAdapter); return rootView; } @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { //define the projections that will be used String[] projections = { StoreEntry._ID, StoreEntry.COLUMN_PRODUCT_NAME, StoreEntry.COLUMN_PRODUCT_PRICE, StoreEntry.COLUMN_PRODUCT_QUANTITY, StoreEntry.COLUMN_PRODUCT_WEIGHT, StoreEntry.COLUMN_SUPPLIER_NAME, StoreEntry.COLUMN_SUPPLIER_NUMBER, }; return new CursorLoader(getActivity(), StoreEntry.CONTENT_URI, projections, null, null, null); } @Override public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor data) { mCursorAdapter.swapCursor(data); } @Override public void onLoaderReset(@NonNull Loader<Cursor> loader) { mCursorAdapter.swapCursor(null); } }
这样修改后,类型不兼容的问题就解决了,同时也修复了潜在的ListView空指针问题,你的Loader就能正常工作啦!
内容的提问来源于stack exchange,提问作者Wissam

