为了账号安全,请及时绑定邮箱和手机立即绑定

当 AsyncTask 的 doInBackground 内部时列表读为空

当 AsyncTask 的 doInBackground 内部时列表读为空

慕的地8271018 2023-09-20 16:26:45
doInBackground我正在尝试读取of内部的整数列表AsyncTask。当我将列表传递给 的构造函数时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);    }}}
查看完整描述

2 回答

?
ITMISS

TA贡献1871条经验 获得超8个赞

这不是您使用 AsyncTask 的方式。您需要声明参数,然后在回调中接收它们。


另请注意,您正在尝试以您的方式从两个线程(主线程和后台线程)访问相同的数据(IDsToDelete),而没有适当的同步。


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是如何工作的),线程将其缓存刷新到主内存,然后也从中读取。这就是数据共享的方式。这就是为什么最好使用框架方式,因为框架将负责在线程之间正确发布数据。你可以接受不可变的数据,但列表不是这样的。即使您将引用声明为不可变,

只是要明确一点。我并不是说以前的方法不起作用。我是说这是出于善意。您不能只是在线程之间共享数据并希望它起作用。


查看完整回答
反对 回复 2023-09-20
?
摇曳的蔷薇

TA贡献1793条经验 获得超6个赞

弄清楚了。为将来可能有类似问题的人发帖。

令人尴尬的是,它ArrayList<Integer>变空了,因为我mAdapter.exitDeleteMode();在调用后在函数中删除了它AsyncTask().execute()

我不知道当我将列表发送到时,AsyncTask它是列表的确切地址,而不仅仅是一个新列表(也就是说,直到我发布上面的评论,然后它点击)。我想我的思路是从 C++ 或其他语言那里得到的。我不记得是哪一个了。

解决方案:我想出的解决方案是直接移入mAdapter.exitDeleteMode()ofonPostExecute()而不是将其放在onClick()方法中。

另一个潜在的解决方案:我相信另一个可行的解决方案(但我没有测试)是将 a 插入new ArrayList<Integer> ()AsyncTask


查看完整回答
反对 回复 2023-09-20
  • 2 回答
  • 0 关注
  • 95 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信