如何将自定义类型的ArrayList传入AsyncTask的doInBackground方法
问题原因和解决方法
1. 泛型拼写错误
你定义MyAsyncTask时的第一个泛型参数存在拼写错误:你写的是ArrayList<CustomoClass>,多了一个字母o,和实际需要的CustomClass不匹配。这个错误会触发泛型擦除的异常逻辑,导致可变参数接收时类型转换异常,最终拿到的列表不符合预期。
先把这处拼写修正:
private static class MyAsyncTask extends AsyncTask<ArrayList<CustomClass>, Void, Void>{ // 其余逻辑不变 }
2. 引用传递导致列表被主线程修改
ArrayList是引用类型,你通过execute传入的只是列表的内存地址,不是复制的副本。如果在调用execute(itemArrayList)之后,主线程立刻对原itemArrayList执行了clear()、重新赋值等清空操作,由于AsyncTask是异步执行的,doInBackground的子线程调度存在延迟,等子线程执行时拿到的就是已经被清空的列表。
这种情况你可以传入列表的副本避免被原列表修改影响:
void deleteAsync(ArrayList<CustomClass> itemArrayList){ Log.i("TEST_SHOP", "deleteAsync() itemArrayList: " + itemArrayList.toString()); // 传入新复制的列表,原列表修改不会影响AsyncTask内部的副本 new MyAsyncTask(dao).execute(new ArrayList<>(itemArrayList)); }
3. 可选优化:规避可变参数的泛型擦除问题
可变参数结合泛型容易出现擦除异常,你也可以直接把列表放到MyAsyncTask的构造方法里传递,更稳妥:
private static class MyAsyncTask extends AsyncTask<Void, Void, Void>{ private final Dao dao; private final ArrayList<CustomClass> list; public MyAsyncTask(Dao dao, ArrayList<CustomClass> list) { this.dao = dao; this.list = list; } @Override protected final Void doInBackground(Void... voids) { Log.i("TEST_SHOP", "doInBackground() arrayList: " + list.toString()); // 其余逻辑不变 return null; } } // 调用方式 void deleteAsync(ArrayList<CustomClass> itemArrayList){ Log.i("TEST_SHOP", "deleteAsync() itemArrayList: " + itemArrayList.toString()); new MyAsyncTask(dao, new ArrayList<>(itemArrayList)).execute(); }
内容的提问来源于stack exchange,提问作者Christopher Hollis
相关产品推荐
相关产品推荐

