Java 在AsyncTask的doInBackground内时,列表读取为空
我正在尝试读取AsyncTask的doInBackground中的整数列表。当我将列表传递到AsyncTask的构造函数中时,它已满。但是,当我到达doInBackground函数时,它是空的。有什么想法吗Java 在AsyncTask的doInBackground内时,列表读取为空,java,android,android-asynctask,Java,Android,Android Asynctask,我正在尝试读取AsyncTask的doInBackground中的整数列表。当我将列表传递到AsyncTask的构造函数中时,它已满。但是,当我到达doInBackground函数时,它是空的。有什么想法吗 public class floatingActionButtonClickListener implements View.OnClickListener{ @Override public void onClick(View v) { if(mAdapt
public class floatingActionButtonClickListener implements View.OnClickListener{
@Override
public void onClick(View v) {
if(mAdapter.getDeleteModeStatus()){
// Delete items from database
ArrayList<Integer> IDsToDelete = mAdapter.getJournalIDsToDelete();
new DeleteDatabase().execute(IDsToDelete);
// Turn FAB back to regular button
mFAB.setImageResource(R.drawable.baseline_add_white_48); // Turn FAB to delete button
// Disable delete mode
mAdapter.exitDeleteMode();
// Load database
new LoadDatabase().execute();
}
else{
Intent intent = new Intent(getBaseContext(), AcitivtyJournal.class);
int journalType = Constants.JOURNALTYPE_FULL;
intent.putExtra(Constants.JOURNAL_TYPE, journalType);
startActivity(intent);
}
}
}
private class DeleteDatabase extends AsyncTask <ArrayList<Integer>, Void, Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
mProgressBarHolder.setVisibility(View.VISIBLE);
}
@Override
protected Void doInBackground(ArrayList<Integer>... arrayLists) {
ArrayList<Integer> IDsToDelete = arrayLists[0];
AppDatabase db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "JournalEntries")
.build();
for(Integer idToDelete : IDsToDelete){
db.mJournalEntriesDao().deleteCompleteJournalEntry(idToDelete);
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
mProgressBarHolder.setVisibility(View.GONE);
}
}
}这不是您使用和异步任务的方式。您需要声明参数,然后在回调中接收它们 还请注意,您试图以自己的方式从两个线程Main和Background访问相同的dataIDsToDelete,但没有进行适当的同步
private class DeleteDatabase extends AsyncTask<ArrayList<Integer>, Void, Void> {
@Override
protected Void doInBackground(ArrayList<Integer>... arrayLists) {
ArrayList<Integer> params = arrayLists[0];
// Do what you need
}
}
ArrayList<Integer> IDsToDelete = mAdapter.getJournalIDsToDelete();
new DeleteDatabase().execute(IDsToDelete);
当您使用多线程时,需要考虑两件事:
操作的原子执行
内存可见性
有一个共享内存,每个CPU都缓存数据。当你从一个线程创建一些东西时,你不能期望第二个线程会直接读取它。在本例中,您正在创建AsyncTask并从一个线程中注入参数,但随后在doInBackground中从另一个线程中读取它们。一般来说,当您通过一个同步块或命中一个易失性变量时,我一般说,因为我也不完全理解JVM是如何工作的,线程将其缓存刷新到主内存,然后也从中读取。这就是数据共享的方式。这就是为什么最好使用框架方式,因为框架将负责在线程之间正确发布数据。您可以使用不可变数据,但列表不是这样的东西。即使您将引用声明为不可变的,您可能会从两个线程中看到正确的对象,但它们所持有的数据可能是旧的
我只是想说清楚。我并不是说前面的方法不起作用。我是说这是出于善意。你不能只在两个线程之间共享数据,然后希望它能工作。解决了这个问题。为将来可能有类似问题的人发布 令人尴尬的是,ArrayList为空,因为我在函数mAdapter.exitDeleteMode中删除了它;在我调用AsyncTask.execute之后 我没有意识到,当我将列表发送到AsyncTask时,它是列表的确切地址,而不仅仅是一个新列表,直到我发布了上面的评论,然后它点击了。我想我从C++或其他语言中得到了这一思路。我不记得是哪个了 解决方案:我提出的解决方案是只将mAdapter.exitdeletmode移动到onpostExecute的中,而不是将其移动到onClick方法中
另一个可能的解决方案:我相信另一个可行但我没有测试的解决方案是,在调用DeleteDatabase的AsyncTask中插入一个新的ArrayList?您怎么知道mAdapter.getJournalidStodelet返回了一个完整的列表?你在任何地方记录它的大小吗?@cricket\u 007我知道是因为调试器。在调用DeleteDatabase之前和调用过程中调用IDsToDeletecallbacks@JohnJoeDeleteDatabase是在onClickListener中为FloatingActionButton调用的。我在上面添加了代码。谢谢Yavor,我就是这样做的;然而,我仍然有同样的问题。这很奇怪,因为在这些图片中,您可以看到ArrayList和从同一地址获取信息,AsyncTask中的一个就是empy。顺便说一句,我试图以什么方式不同步?我认为这是因为我正在调用mAdapter.getJournalidStodelet;在调用DeleteDatabase;之前;。这样,将在调用DeleteDatabase之前填充IDsToDelete。没有足够的空间作为注释回复您。关于你为什么看不到数据。。。我和你一样惊讶。