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が含まれています.コードは以下の通りです.
ダイアログボックスにLayoutレイアウトファイルを新規作成しました.このR.id.photoはこのファイルに保存されます.しかし、実行時には常にエラーが発生します.
java.lang.NullPointerException: Attempt to invoke virtual method '........' on a null object reference
問題の原因はphotoが正しく初期化されていないことです.
考えてみると、私はすべて関連しているのに、コンパイルも大丈夫で、正しく初期化できるはずです.
そしてfindViewById()の原理を思いつき、それまではむやみに使っていた.このエラーでfindViewById()の設定が不適切かもしれないことに気づきました.
一般的にfindViewById()はActivityのOnCreate()メソッドの中にあります.たとえば、次のようになります.
ここで(Button)は省略できます.
ここでfindViewById()関数はActivityクラスから来ています.
ここで、ViewクラスのfindView ById()メソッドは次のとおりです.
私が上記のエラーを起こしたのは、どのfindViewById()を使うべきか分からなかったからです.getView()を呼び出すと現在表示されているViewが得られるはずですが、ここで表示するのはDialogダイアログボックス専用の新しいレイアウトファイルなので、現在のViewオブジェクトでImageViewを初期化することはできません.
解決策は、新しいクラス継承Dialogクラスを作成し、表示する要素を定義し、再OnCreate()メソッドを再作成することです.
元のFragmentでは簡単な2つの文しか必要ありません.
とにかく複雑なDialogを作成するには、Dialogメソッドを書き直して、めちゃくちゃなものを元のクラスに押し込まないほうがいいです.
初心者としては、コードを少しOOPに書こうとすることもあるでしょうが、他人の優れたコードを見て、コードの長さではなく、具体的な機能実現が必要かどうかによって、解結合するかどうかは経験の積み重ねが必要だと感じています.こんな簡単な問題を午後中やって、本当に自分に泣かれた.
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に書こうとすることもあるでしょうが、他人の優れたコードを見て、コードの長さではなく、具体的な機能実現が必要かどうかによって、解結合するかどうかは経験の積み重ねが必要だと感じています.こんな簡単な問題を午後中やって、本当に自分に泣かれた.