【问题标题】:Data appears before onPostExecute fired数据出现在 onPostExecute 触发之前
【发布时间】:2015-07-07 18:10:29
【问题描述】:

我有下一个奇怪的问题,我试图在后台使用 JSON 数据解析响应,因为有很多数据并这样称呼它:

protected AsyncTask<JSONObject, Void, Void> createParseTask() {

    return new AsyncTask<JSONObject, Void, Void>() {
        @Override
        protected Void doInBackground(JSONObject... jsonObjects) {
            parseResponse(jsonObjects[0]);
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);

            mProgressBar.setVisibility(View.GONE);
            if (!mEmpty) {
                if (swipeRefresh.isRefreshing()) {
                    swipeRefresh.setRefreshing(false);
                    mAdapter.notifyDataSetChanged();
                } else if(!mShowStored) {
                    mAdapter.notifyDataSetChanged();
                }
            } else if (mShowStored) {
                mProgressBar.setVisibility(View.GONE);
            } else {
                internetError.setVisibility(View.VISIBLE);
          internetError.setText(getActivity().getResources().getString(R.string.emptyRequestError));
            }

            if (!mShowStored) {
                checkData();
            }

        }
    };

}

而parseResponse()方法是这样写的:

protected void parseResponse(JSONObject response) {

    JSONArray jsonArray = null;
    JsonParser parser = new JsonParser();
    OrdersDatabase ordersDatabase = new OrdersDatabase(AppController.getAppContext());
    try {
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(AppController.getAppContext());
        SharedPreferences.Editor editor = sp.edit();
        String dateTime = response.getString("serverDateTime");
        dateTime = dateTime.replace(":", "%3A");
        dateTime = dateTime.replace("+", "%2B");
        editor.putString("serverDateTime", dateTime);
        editor.apply();
        jsonArray = response.getJSONArray("updatedOrders");
        JSONArray active = response.getJSONArray("activeOrders");
        if (jsonArray.length() == 0 && active.length() == 0) {
            mEmpty = true;
        } else if (response.length() > 0 || jsonArray.length() > 0 && active.length() > 0) {
            for (int i = 0; i < jsonArray.length(); i++) {
                JsonElement jsonElement = new JsonParser().parse(String.valueOf(jsonArray.get(i)));
                JsonObject jsonObject = jsonElement.getAsJsonObject();

                String orderID = jsonObject.getAsJsonPrimitive("id").getAsString();

                if (!mShowStored) {
                    if (!ordersDatabase.checkOrder(orderID)) {
                        ordersDatabase.addOrderData(jsonObject.getAsJsonPrimitive("id").getAsString(), String.valueOf(jsonObject));
                    } else {
                        ordersDatabase.updateOrderData(jsonObject.getAsJsonPrimitive("id").getAsString(), String.valueOf(jsonObject));
                    }
                }
            }
            for (int i = 0; i < active.length(); i++) {
                JSONObject jsonObject = active.getJSONObject(i);
                String activeOrder = jsonObject.getString("id");
                activeOrders.add(activeOrder);
                if (ordersDatabase.checkOrder(activeOrder)) {
                    if (!TextUtils.isEmpty(activeOrder)) {
                        JsonObject jsonOrder = (JsonObject) parser.parse(ordersDatabase.getOrderData(activeOrder));
                        cityList.add(OrderData.fromJson(jsonOrder));
                    }
                }
            }

        }

    } catch (JSONException e) {
        e.printStackTrace();
    }
}

所以我不知道如何,但不知何故,在显示 onPostExecute 之前,RecyclerView 中出现的数据就在那里,因为在执行后,进度条应该不可见,notifydatasetchange 也应该出现在那里。但是数据出现在进度条不可见并且notifyDataSetChange() 被解雇之前,请帮助我!

【问题讨论】:

  • 有点不清楚是什么问题。 onPostExecute() 永远不会“显示”而是调用。是什么让您认为 RV 在调用该方法之前已被填充?
  • @codeMagic 因为在执行后进度条应该不可见,并且 notifydatasetchange 也应该出现在那里。但数据会在进度条不可见和notifyDataSetChange() 被触发之前出现。
  • 移除 super.onPostExecute 调用。
  • @greenapps super.onPostExecute() 什么都不做。
  • 'mProgressBar.setVisibility(View.GONE);'。使用 mProgressBar.dismiss();而是。

标签: java android android-asynctask


【解决方案1】:

我没有评论的权利,所以我会在这里发布: 你的ordersDatabasecityListactiveOrders 上没有听众?

【讨论】:

  • 我猜不,因为我认为我实际上并不需要那些听众。
  • 我建议通过parseResponse 方法进行调试并找出UI 更新的确切位置。
  • 我已经这样做了,但没有什么可以解决我的问题。
【解决方案2】:

AsyncTask 不从doInBackground() 返回任何内容(并且不通过私人成员与onPostExecute() 通信)总是可疑的。

你的AsyncTask 有很多副作用,而且这种东西很难调试。例如,您添加到cityListactiveOrders,但没有显示实际是什么。大概这些是附加到某些Adapter 的列表,添加到这些列表可能会触发附加到AdapterView 被重新绘制。如果是这种情况,您可以尝试在mAdapter 上调用setNotifyOnChange(false)(延迟更新,直到您稍后手动调用notifyDataSetChanged())。

http://developer.android.com/reference/android/widget/ArrayAdapter.html#setNotifyOnChange(boolean)

一般来说,如果您的AsyncTask 没有返回任何内容或以其他方式与onPostExecute()“交流”,那么首先拥有onPostExecute() 就毫无意义。更好的是不要在doInBackground() 中产生任何副作用,而是返回解析后的数据并仅将其添加到onPostExecute() 中的cityListactiveOrders

多线程很棘手,AsyncTasks 在出现/尝试使其更容易时,有很多陷阱。我试图回答AsyncTaskhere的线程安全问题

【讨论】:

  • citylistactivOrders 是 ArrayLists,是的。问题是我没有使用 ArrayAdapter,我使用的是 RecyclerView.Adapter,但它没有 setNotifyOnChange(false)
  • 你能说明你在哪里以及如何使用citylistactiveOrders吗?
猜你喜欢
  • 1970-01-01
  • 2015-01-23
  • 2011-11-18
  • 2020-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-22
相关资源
最近更新 更多