Android - ListView 为空时出现 AsyncTask 错误?

Android - AsyncTask error when ListView empty?

我有一个使用选项卡和片段的应用程序。在我的一个选项卡上,我有一个包含页眉视图和页脚视图的 ListView。

列表中的项目是通过我使用 AsyncTask 获得的 XML 提要从我的数据库中收集的。当我在列表中列出项目时,一切都按预期进行。但是,我注意到当我没有任何项目并且我的列表视图为空时,当我尝试切换选项卡时出现以下错误。

java.lang.IllegalStateException: Fragment Pending{3223f5a4} not attached to Activity

如果我的数据返回为空,我会调用 myList.setAdapter(null),这样我至少可以看到我的列表 header/footer,但我已将其注释掉以消除它的可能性,并且它仍然轰炸我。

什么会导致这种情况发生?同样,当我在异步任务中输入数据 return 时,一切正常。

我可以根据需要添加更多代码,但我想等一下,看看是否有人立即知道是什么原因造成的。

导致问题的 AsyncTask

private class GetMaintenanceRequestsPending extends AsyncTask<String, Integer, Integer>
    {
        @Override
        protected void onPreExecute() { 
            progressDialog = ProgressDialog.show(getActivity(), "", getResources().getString(R.string.general_msg_please_wait));
        }

        @Override
        protected Integer doInBackground(String... params) {
            //First check if network is connected, if not take user to network error activity.
            if(!NetworkStatus.getInstance(getActivity().getApplicationContext()).isOnline(getActivity().getApplicationContext())) {
                return AppConstants.STATUS_NETWORK;
            }
            try {       
                getMaintenancePending(params[0],params[1]);
                if (maintenancePendingData == null) {
                    return AppConstants.STATUS_ERROR;
                } else {
                    return AppConstants.STATUS_SUCCESS;
                }
            } catch (Exception e) {
                return AppConstants.STATUS_ERROR;
            } 
        }

        @Override
        protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); }

        @Override
        protected void onPostExecute(Integer result) {
            // NETWORK ERROR HAS OCCURRED - SHOW NETWORK ACTIVITY
            if (result == AppConstants.STATUS_NETWORK) {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        progressDialog.dismiss();
                        Intent networkError = new Intent(getActivity(), NetworkError.class);
                        networkError.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        startActivity(networkError);
                        getActivity().finish();
                    }
                }, 1000);
            }
            // ERROR OCCURRED
            else if (result == AppConstants.STATUS_ERROR ) {
                progressDialog.dismiss();
                alertDialog.showAlertDialog(getActivity(), getString(R.string.error), getString(R.string.error_connect), false, false);
            }
            else {
                // SUCCESS!
                layoutMaintenanceSwipeRefresh.setRefreshing(false);
                Globals.refreshMaintenanceRequestData = false;
                setupPendingRequests();
            }
        }
    }       

我不明白的是为什么我的 AsyncTask 中的某些东西无论如何都会被触发?它在选项卡加载时被调用,而我正在离开选项卡,那么为什么它会再次被调用?

此外,AsyncTask onPostExecute 方法的 setupPendingRequests() 方法确实被调用。一切看起来都像它应该的那样工作......直到我尝试切换标签。然后它抛出错误。我注意到它有时会说 WindowLeaked 作为错误,而其他时候则没有附加到 activity.

更新 8.24.16

所以我检查了我的代码并尝试删除我能想到的任何会导致此错误的内容。这是我发现的。在我的片段中,我使用下面的代码在动画完成后触发我的 UI 工作(AsyncTask,并设置 ui 元素值)。当我的列表视图为空时,无论出于何种原因,这种方法都是导致我出现问题的原因。

//@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
        Animation animation = super.onCreateAnimation(transit, enter, nextAnim);
        final Boolean fragmentShown = enter;
        if (animation == null && nextAnim != 0) {
            animation = AnimationUtils.loadAnimation(getActivity(), nextAnim);
        }
        if (animation != null) {
            if (getView() != null) {
                getView().setLayerType(View.LAYER_TYPE_HARDWARE, null);
                animation.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {
                    }

                    public void onAnimationEnd(Animation animation) {
                        getView().setLayerType(View.LAYER_TYPE_NONE, null);
                        if (fragmentShown) {
                            new Handler().postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    setupFragment();
                                }
                            }, 200);
                        }
                    }
                });
            }
        } else {
            setupFragment();

根据我对这种方法工作原理的理解,当我调用 if (fragmentShown) { ...my Ui stuff } 时,我正在等待片段的动画完成,然后开始我的工作.我也在检查动画是否为空,然后没有为该片段设置动画并调用 ui 东西。

当我的列表视图数据集为空时,为什么这种方法会导致问题? 我不明白。我通过删除此方法并将我的 setupFragment() 调用放在片段的 onResume() 方法中来修复它。但我想了解为什么会发生这种情况,以及是否可以以某种方式修复它以将动画方法保留在那里。 } return动画; }

因为您正在您的应用程序中执行后台任务。无法保证用户在任务完成之前会停留在同一屏幕上,因此如果用户在任务完成之前导航到其他屏幕或按下主页按钮;您的片段与 activity 分离。因此,请务必确保您的片段附有 Activity。尝试检查

if (isAdded) {
//Do your UI stuff here
}

有关更多详细信息,请访问此 link:

Fragment MyFragment not attached to Activity

我不确定它对你有用,因为你没有显示你的整个代码,但它对我有用,我只是在 Recyler 视图片段中添加这个方法

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);

  if (isVisibleToUser && mDataset.isEmpty()) {

        Log.i(TAG, "start Asyc task ");

        new LoadRssFeedsItems(getActivity()).execute(Constants.DW_HOME_PAGE_URL);


    }

}