24

私はいくつかのバックグラウンド作業を行っており、その間に DialogFragment を表示しています。作業が完了し、関連するコールバックが呼び出されたら、ダイアログを閉じます。すると、Android ソースの NPE が原因でクラッシュが発生します。

void dismissInternal(boolean allowStateLoss) {
        if (mDialog != null) {
            mDialog.dismiss();
            mDialog = null;
        }
        mRemoved = true;
        if (mBackStackId >= 0) {
            getFragmentManager().popBackStack(mBackStackId,
                    FragmentManager.POP_BACK_STACK_INCLUSIVE);
            mBackStackId = -1;
        } else {
            FragmentTransaction ft = getFragmentManager().beginTransaction();
            ft.remove(this);
            if (allowStateLoss) {
                ft.commitAllowingStateLoss();
            } else {
                ft.commit();
            }
        }
    }

具体的には次の行で:FragmentTransaction ft = getFragmentManager().beginTransaction();

4

6 に答える 6

11

最も簡単な解決策は、「dismiss()」メソッドを呼び出す前に「getFragmentManager()」で「null」をチェックすることです。また、「DialogFragment」クラスを拡張し、メソッド「dismiss()」をオーバーライドして、そこでチェックすることもできます。

@Override
public void dismiss()
{
    if (getFragmentManager() != null) super.dismiss();
}
于 2013-11-14T14:55:03.200 に答える
7

このメッセージが古いことは承知していますが、多くのコードをリファクタリングしたり変更したりせずに解決する必要がある同様のケースに遭遇しました。それが誰かに役立つことを願っています

   package com.example.playback;

import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class SaferDialogFragment extends DialogFragment {

    private boolean allowStateLoss = false;
    private boolean shouldDismiss = false;

    public SaferDialogFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    @Override
    public void onStart() {
        super.onStart();
        //check if we should dismiss the dialog after rotation
        if (shouldDismiss) {
            if (allowStateLoss)
                dismissAllowingStateLoss();
            else
                dismiss();
        }
    }

    @Override
    public void dismiss() {
        if (getActivity() != null) { // it's "safer" to dismiss
            shouldDismiss = false;
            super.dismiss();
        } else {
            shouldDismiss = true;
            allowStateLoss = false;
        }
    }

    @Override
    public void dismissAllowingStateLoss() {
        if (getActivity() != null) { // it's "safer" to dismiss
            shouldDismiss = false;
            super.dismissAllowingStateLoss();
        } else
            allowStateLoss = shouldDismiss = true;
    }

    //keeping dialog after rotation
    @Override
    public void onDestroyView() {
        if (getDialog() != null && getRetainInstance())
            getDialog().setDismissMessage(null);
        super.onDestroyView();
    }



    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        /** omitted code **/
        return super.onCreateView(inflater, container, savedInstanceState);
    }
}
于 2014-04-23T18:08:02.800 に答える
5

あなたが投稿したコードはバックグラウンド スレッドからのものであると思います... UI スレッド以外の場所から UI を更新することは許可されていません。

onPostExecute() または runOnUiThread() を使用して目標を達成できます (何が起こっているかについて私の推測が正しければ)

于 2012-05-10T03:07:44.683 に答える
1

呼び出されるコールバックは、おそらく (向きの変更後に) 破棄される、または破棄される必要があるアクティビティにあり、進行状況ダイアログも同じアクティビティでインスタンス化されている可能性があります。これにより、NPE が発生する可能性があります。この種の問題を防ぐために、バックグラウンド タスクからアクティビティのコールバックを呼び出さないでください。otto を使用するなどしてバックグラウンド タスクをアクティビティから切り離すか、バックグラウンド タスクが破棄されるアクティビティを呼び出さないようにします。

これは私のコードです:

アクティビティの静的内部クラス:

    public static class ProgressDialogFragment extends DialogFragment {
    ProgressDialog dialog;

    public ProgressDialogFragment() {
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        dialog = new ProgressDialog(getActivity(), getTheme());
        dialog.setTitle(getString(R.string.please_wait));
        dialog.setMessage(getString(R.string.uploading_picture));
        dialog.setIndeterminate(true);
        dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        return dialog;
    }

}

活動中の Otto サブスクリプション:

@Subscribe
public void onUploadEvent(UploadAvatarEvent uploadAvatarEvent) {
    switch (uploadAvatarEvent.state) {
        case UploadAvatarEvent.STATE_UPLOADING:
            if (!mProgressDialog.isAdded()) {
                mProgressDialog.show(getFragmentManager(), TAG_PROGRESS_DIALOG);
            }
            break;
        case UploadAvatarEvent.STATE_UPLOAD_SUCCES:
            mProgressDialog.dismiss();
            break;
        case UploadAvatarEvent.STATE_UPLOAD_ERROR:
            mProgressDialog.dismiss();
            break;
    }
}

アクティビティの onCreate():

        mProgressDialog = (ProgressDialogFragment) getFragmentManager().findFragmentByTag(TAG_PROGRESS_DIALOG);
    if (mProgressDialog == null) {
        mProgressDialog = new ProgressDialogFragment();
    }
于 2015-03-05T20:56:25.463 に答える
1

消す前に可視かどうかを確認すると、このヌルポインター例外を回避できます

    if (mDialog != null && mDialog.isVisible) {
        mDialog.dismiss();
        mDialog = null;
    }
于 2013-10-16T15:30:10.577 に答える