Android开发中出现Attempt to invoke virtual method...on a null object reference
摘要:
加载Android布局文件时出现错误:
java.lang.NullPointerException: Attempt to invoke virtual method '........' on a null object reference
出错原因可能是未能在正确的View环境下使用findViewById()方法。
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中使用findViewById()时候,需要创建Fragment的View对象,然后调用View对象的findViewById()方法。 View v = inflater.inflate(R.layout.fragment, container, false);listView = v.findViewById(R.id.list_view);
其中View类中findViewById()方法如下:
@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中只需要简单的两句:
MyDialog myDialog = new MyDialog(getContext());myDialog.show();
总之就是要创建一个复杂的Dialog,最好重写Dialog方法,别把乱七八糟的东西都挤到原来的类里。
作为一个初学者,有时候吧,想把代码写得OOP一点,但是看到别人的优秀代码,感觉其实要不要解耦不取决于代码的长短,而取决于具体的功能实现是否需要,这个还是需要经验的积累吧。
这么简单的问题搞了一下午,真的是被自己蠢哭了。更多相关文章
- Android(安卓)解决setRequestedOrientation之后手机屏幕的旋转不
- android截图代码
- Android一键锁屏代码
- android 四大组件之Service
- Android(安卓)Drawable 系列——ClipDrawable
- Android(安卓)UI测量、布局、绘制过程探究
- 【Android】adapter has changed解决方法
- 浅谈Java中Collections.sort对List排序的两种方法
- Python list sort方法的具体使用