Android開発中にAttempt to invoke virtual methodが登場...on a null object reference

3227 ワード

要約:
Androidレイアウトファイルをロード中にエラーが発生しました:java.lang.NullPointerException: Attempt to invoke virtual method '........' on a null object referenceエラーの原因は、findViewById()メソッドを正しいView環境で使用できなかった可能性があります.
Android初心者で、何も分かりません.
ListViewを作成し、機能を実現したい:Itemをクリックし、ダイアログボックスをポップアップし、ダイアログボックスにImageViewが含まれています.コードは以下の通りです.
ImageView photo;
Bitmap bitmap = BitmapFactory.decodeStream(
        getContext().getContentResolver().openInputStream(uri));
ImageView photo = getView().findViewById(R.id.photo);
photo.setImageBitmap(bitmap);
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setView(R.id.dialog);
/*      */
AlertDialog dialog = builder.create();
dialog.show();

ダイアログボックスにLayoutレイアウトファイルを新規作成しました.このR.id.photoはこのファイルに保存されます.しかし、実行時には常にエラーが発生します.
java.lang.NullPointerException: Attempt to invoke virtual method '........' on a null object reference
問題の原因はphotoが正しく初期化されていないことです.
考えてみると、私はすべて関連しているのに、コンパイルも大丈夫で、正しく初期化できるはずです.
そしてfindViewById()の原理を思いつき、それまではむやみに使っていた.このエラーでfindViewById()の設定が不適切かもしれないことに気づきました.
一般的にfindViewById()はActivityのOnCreate()メソッドの中にあります.たとえば、次のようになります.
button = (Button)findViewById(R.id.button);

ここで(Button)は省略できます.
ここでfindViewById()関数はActivityクラスから来ています.
public  T findViewById(@IdRes int id) {
        return getWindow().findViewById(id);
    }
FragmentでfindView ById()を使用する場合は、FragmentのViewオブジェクトを作成し、ViewオブジェクトのfindView ById()メソッドを呼び出す必要があります.
View v = inflater.inflate(R.layout.fragment, container, false);
listView = v.findViewById(R.id.list_view);

ここで、ViewクラスのfindView ById()メソッドは次のとおりです.
@Nullable
    public final  T findViewById(@IdRes int id) {
        if (id == NO_ID) {
            return null;
        }
        return findViewTraversal(id);
    }
具体的には研究しません(どうせ私のレベルも分かりません)
私が上記のエラーを起こしたのは、どのfindViewById()を使うべきか分からなかったからです.getView()を呼び出すと現在表示されているViewが得られるはずですが、ここで表示するのはDialogダイアログボックス専用の新しいレイアウトファイルなので、現在のViewオブジェクトでImageViewを初期化することはできません.
解決策は、新しいクラス継承Dialogクラスを作成し、表示する要素を定義し、再OnCreate()メソッドを再作成することです.
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LayoutInflater inflater = (LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View layout = inflater.inflate(R.layout.photo_dialog, null);
        photo = layout.findViewById(R.id.photo);
        try{
            Bitmap bitmap = BitmapFactory.decodeStream(
                    getContext().getContentResolver().openInputStream(uri));
            photo.setImageBitmap(bitmap);
        }catch (Exception e){
            e.printStackTrace();
        }
        this.setContentView(layout);
    }
}

元のFragmentでは簡単な2つの文しか必要ありません.
MyDialog myDialog = new MyDialog(getContext());
myDialog.show();

とにかく複雑なDialogを作成するには、Dialogメソッドを書き直して、めちゃくちゃなものを元のクラスに押し込まないほうがいいです.
初心者としては、コードを少しOOPに書こうとすることもあるでしょうが、他人の優れたコードを見て、コードの長さではなく、具体的な機能実現が必要かどうかによって、解結合するかどうかは経験の積み重ねが必要だと感じています.こんな簡単な問題を午後中やって、本当に自分に泣かれた.