Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/221.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在AsyncTask的doInBackground内时,列表读取为空_Java_Android_Android Asynctask - Fatal编程技术网

Java 在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

我正在尝试读取AsyncTask的doInBackground中的整数列表。当我将列表传递到AsyncTask的构造函数中时,它已满。但是,当我到达doInBackground函数时,它是空的。有什么想法吗

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。没有足够的空间作为注释回复您。关于你为什么看不到数据。。。我和你一样惊讶。