【问题标题】:Asynctask ArrayList object not passing from doInBackground to onPostExecuteAsynctask ArrayList 对象未从 doInBackground 传递到 onPostExecute
【发布时间】:2014-04-30 20:43:37
【问题描述】:

我有一个AsyncTask,它接收上下文(使用onPostExecute)并运行doInBackground 以从服务器返回对象的ArrayList。当我执行这个时,我可以看到doInBackground 运行良好,但是它没有将结果传递给onPostExecute。

经过大量搜索,我还没有找到关于如何在AsyncTask 中返回对象的 ArrayList 的答案。

这是我在doInBackground 中使用onPostExecute 创建的对象:

public class ServerTimeCard {

    public String eventNameInput;
    Boolean isLocation, isImage, isVoice;

    public ServerTimeCard(String eventNameInput, boolean isLocation, boolean isImage, boolean isVoice) {
        this.eventNameInput = eventNameInput;
        this.isLocation = isLocation;
        this.isImage = isImage;
        this.isVoice = isVoice;
    }

}

我在onCreate 中执行AsyncTask 和new LoadFriendCards(context).execute();。

  • 预期输出: doInBackground 应该返回一个 ArrayList 到 onPostExecute

  • 当前输出:onPostExecute 中的ArrayList<ServerTimeCard> 的大小为零,而doInBackground 中的相同arraylist 具有更大的大小。

以下是AsyncTask代码。

public class LoadFriendCards extends AsyncTask<Void, Void, ArrayList<ServerTimeCard>> {

            Context context;
            ArrayList<ServerTimeCard> result;

            public LoadFriendCards(Context context) {
                this.context = context;
            }

            @Override
            protected ArrayList<ServerTimeCard> doInBackground(Void... voids) {

                     result = new ArrayList<ServerTimeCard>();

                     // ...a bunch of data retrieval goes on here...    

                     // querying parse for object info
                     // adding a new object to the local ArrayList for all in db
                     for (String friend : friendsListNames) {
                          ParseQuery<ParseObject> query = ParseQuery.getQuery("TestObject");
                          query.whereEqualTo("accountName", friend+"@gmail.com");
                          query.findInBackground(new FindCallback<ParseObject>() {
                          public void done(List<ParseObject> objects, ParseException e) {
                          if (e == null) {

                               for (ParseObject cardInfo : objects) {

                                   ServerTimeCard item = new ServerTimeCard(
                                      cardInfo.getString("eventName"),
                                      cardInfo.getBoolean("isImage"),
                                      cardInfo.getBoolean("isImage"),
                                      cardInfo.getBoolean("isVoice"));

                                   result.add(item);


                        Log.e("New item called: ", String.valueOf(item.eventNameInput));
                        Log.e("New size of array...", String.valueOf(result.size()));

                    }

                } else {
                    Log.d("info", "Error: " + e.getMessage());
                }
            }
        });
    }

                // returning the new ArrayList<ServerTimeCard> to onPostExecute

                // PROBLEM: THE SIZE OF THE RESULT IS 0
                Log.e("Size of passing array", String.valueOf(result.size()));

                return result;
            }

            @Override
            protected void onPostExecute(ArrayList<ServerTimeCard> result) {

                // PROBLEM: This returns 0
                Log.e("Data list size: ", String.valueOf(result.size())); 

                // trying to use all objects in the arraylist here but it doesn't work
                // due to the size. Something isn't passing correctly.

            }
        }

Log.e 的 Logcat 输出:(看起来它调用了 doInBackground,然后是 onPostExecute,然后又是 doInBackground)

E/Size of passing array﹕ 0
E/Data list size:﹕ 0
E/New item called:﹕ yah
E/New size of array...﹕ 1
E/New item called:﹕ lplokolol
E/New size of array...﹕ 2
E/New item called:﹕ It works
E/New size of array...﹕ 3

已解决:我最初认为我需要 AsyncTask,但我最终将其全部删除并将所有代码放入我的 Main 类中的一个方法中。我在 asynctask 中一次运行了太多东西,并且结构将数据扔到了各处。经验教训:保持简单。

【问题讨论】:

  • 你能展示一下实际的循环吗?似乎每次迭代都在创建一个新列表,但没有循环就无法判断。
  • 如果您将日志语句放在 doInBackground 方法中的 return result 之前,输出会是什么?
  • @zmbq 添加了 for 循环。我正在 Parse 中查询对象并将它们添加到数组列表中。
  • 当你在doInBackground中下断点时,result什么时候会自行重置?
  • 另外,在result.add(item); 之后添加日志以确保item != null 并在添加后立即查看result.size()。

标签: java android arraylist android-asynctask closures


【解决方案1】:

您的问题是您使用findInBackground 进行查询。该方法在后台线程中完成。因此,您基本上是在异步任务中运行异步任务。

  1. doInBackground
  2. findInBackground -> 异步运行,因此代码继续执行
  3. onPostExecute 在您的查询完成之前被调用。
  4. 然后会调用 done 回叫以获取您的查询以填写您的列表

因此,您需要做的就是在 AsyncTask 之外使用 findInBackground(该方法不能在 AsyncTask 中使用)或使用 find 函数。

【讨论】:

    【解决方案2】:

    您正在匿名内部类中修改result。您的代码看不到您认为它看到的结果,而是一个闭包。这是问题的根源。

    【讨论】:

    • 我看到-通过使用 ParseObject Query 方法(获取数据),我将其添加到后来被销毁的数组中(出于某种未知原因)。我正在谷歌搜索什么是闭包来理解它:)。有什么解决办法吗?
    【解决方案3】:

    您正在启动一个后台线程(您的异步任务),在这里您多次调用query.findInBackground(),这会启动更多后台线程。不过,这不是问题。

    您遇到问题是因为 AsyncTask 在它启动的所有其他线程完成之前完成。只有在调用每个FindCallback 的 done() 方法时,您才知道其他线程已完成。

    如果您想知道正确的大小,您需要以某种方式对其进行编码,以便在最后一个done() 方法中检查大小。

    【讨论】:

      【解决方案4】:

      你不必让 doInBackground 返回一个可以在 onPostExecute 中使用的数组列表。只需返回“ok”或“error”。声明并创建一个私有数组列表作为您询问的成员。然后填入doInBackground,在onPostexecute中使用。

      【讨论】:

        【解决方案5】:

        另一种更简单的方法是将您的 doInBackground 声明为 List 类型。 这是我的例子

            @Override
            protected  ArrayList<ServerTimeCard > doInBackground(String... urls) {
                // Perform the HTTP request for earthquake data and process the response.
                ArrayList<ServerTimeCard > result = QueryUtils.fetchTheData(urls[0]);
                return result;
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-08-03
          • 2013-01-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-18
          相关资源
          最近更新 更多