web-dev-qa-db-ja.com

AndroidフラグメントのSnackbar NullPointerException

アプリケーションに基本的なスナックバーを追加したいのですが、理由がわからないというエラーが表示されます。

このコードをFragmentのonCreateView()メソッドに追加しました。

Snackbar.make(view, "Snackbar", Snackbar.LENGTH_LONG)
            .setAction("Action", null).show();

そして、このエラーを受け取りました:

06-01 10:26:09.955    1232-1232/? E/ActivityThread﹕ Failed to find provider  info for me.muraterdogan.watchme.MetricaContentProvider
06-01 10:26:10.075    1232-1447/? E/ActivityThread﹕ Failed to find provider info for me.muraterdogan.watchme.YPLContentProvider
06-01 10:33:55.044    6646-6646/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: me.muraterdogan.watchme, PID: 6646
Java.lang.NullPointerException: Attempt to invoke virtual method 'Android.content.Context Android.view.ViewGroup.getContext()' on a null object reference
        at Android.support.design.widget.Snackbar.<init>(Snackbar.Java:116)
        at Android.support.design.widget.Snackbar.make(Snackbar.Java:140)
        at me.muraterdogan.watchme.fragments.TrendingFragment.GetData(TrendingFragment.Java:90)
        at me.muraterdogan.watchme.fragments.TrendingFragment.onCreateView(TrendingFragment.Java:83)
...
14
Murat Erdogan

Fragmentが既存のアクティビティに追加された場合(xmlを使用して追加できることを思い出してください)、SnackBarのメソッドをFragmentのonActivityCreated()メソッドに呼び出す必要があります。

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    Snackbar.make(view, "Snackbar", Snackbar.LENGTH_LONG)
        .setAction("Action", null).show();
}
19

1. onActivityCreatedメソッドに移動します。

2.以下のようなmakeメソッドでgetView()を使用してみます。

Snackbar.make(getView(), "Snackbar", Snackbar.LENGTH_LONG)
        .setAction("Action", null).show();
13
Michael

私が取り組んでいるコードベースでは、ネットワークコールのエラーハンドラーなどの非同期メソッドコールバックにSnackbarsが表示されていました。 Snackbarが作成されていたとき、移動するFragmentはアタッチされておらず、getView()から返されたViewにはCoordinatorLayoutまたはFrameLayoutSnackbarは、ビューの階層に含めたいと考えています。

特に、階層を走査するのはSnackbarのプライベート findSuitableParent() メソッドです。

_private static ViewGroup findSuitableParent(View view) {
    ViewGroup fallback = null;
    do {
        if (view instanceof CoordinatorLayout) {
            // We've found a CoordinatorLayout, use it
            return (ViewGroup) view;
        } else if (view instanceof FrameLayout) {
            if (view.getId() == Android.R.id.content) {
                // If we've hit the decor content view, then we didn't find a CoL in the
                // hierarchy, so use it.
                return (ViewGroup) view;
            } else {
                // It's not the content view but we'll use it as our fallback
                fallback = (ViewGroup) view;
            }
        }

        if (view != null) {
            // Else, we will loop and crawl up the view hierarchy and try to find a parent
            final ViewParent parent = view.getParent();
            view = parent instanceof View ? (View) parent : null;
        }
    } while (view != null);

    // If we reach here then we didn't find a CoL or a suitable content view so we'll fallback
    return fallback;
}
_

このメソッドの結果はSnackbarコンストラクターに渡され、そのコンストラクターでgetContext()を呼び出します。このメソッドがnullを返す場合は、質問にあるようにNPEを取得します。

添付されたフラグメントにCoordinatorLayoutまたはFrameLayoutが含まれているという幸せなケースがまだ成り立つと仮定して、問題を修正する方法はいくつかあります。

  1. 最初にisDetached()をチェックして、フラグメントがデタッチされていないことを確認してください。

  2. 私が自分でやったこと:コードベースのSnackbar用の Builderパターン スタイリングラッパーがすでにあったため、ビルダーでfindSuitableParent()をフォークして追加しましたSnackbar.make()を呼び出す前に、それが_!= null_を返すことを確認するチェック。このように、Snackbarビルダーの呼び出し元は、追加のチェックを追加する必要がありませんでした。

3
laalto

プロセスによって、スナックバーはビューを検索します。

  • あなたはフラグメントビューを使用しました
  • ただし、フラグメントのonAttachがまだ呼び出されていないため、フラグメントビュー自体はまだ接続されていません。

そのため、アプリ自体は、実行時にフラグメントのビューを実際に参照していたことを実際には認識していません。

スナックバーのshowメソッドをフラグメントの「onResume」に配置してみてください。お役に立てれば。

2
gorbos

なぜこれをonCreate内で行うのですか?

さらに、いくつかのルールに従っていることを確認してください。

  1. メインのアクティビティがサポートライブラリを使用するために必要であるため、AppCompatActivityを継承するようにしてください。
  2. 渡そうとしているビューが実際に存在することを確認してください(これが、なぜonCreateでこれを行っているのか、なぜないのかを尋ねている理由です)。
1
AkiAki007

ドキュメントに「Snackbarは親ビューを見つけて、ビューに与えられた値からSnackbarのビューを保持しようとします」とあります。

そのため、現在アタッチされている任意のビューを渡すことができます。

0
Daniel Arroyo