Android开发:getViewById返回null的原因定位

最近在研究开发一些基于Android的App,遇到了一些问题,其中一个比较关键的是在Activity中的onCreate()方法中获取Button对象,代码大概如下:

private Button mTrueButton;

@Override

public void onCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_quiz);

mTrueButton = (Button) getViewById(R.id.true_button);

mTrueButton.setOnClickListener(…);

}

该代码是根据一本android的编程指南进行修改的,但意想不到的是,一执行,app提示系统错误,终止运行,通过debug跟踪发现:mTrueButton为null,系统执行到mTrueButton.setOnclickListener抛出java.lang.NullPointerException,很明显,此时调用getViewById无法获取到Button这个View对象,于是开始网上搜索资料,认为可能的原因是下面几个:

一,调用顺序不当导致的异常

持这种观点的主要原因是getViewById的调用放到了setContentView之前,如下:

super.onCreate(savedInstanceState);

mTrueButton = (Button)getViewById(R.id.true_button);

setContentView(R.layout.activity_quiz);

理由是:当activity 调用 setContentView() 时,android 才会去绘制 layout 上的各个元素,并为其分配内存。只有 分配了内存以后,才能继续执行 ,findViewById(); 才能得到引用,不然得到空引用,空引用意味着,后面使用相应变量时就会发生访问的对象不存在的问题。

而且当Activity重新setContentView()以后,那些之前绘制的控件,内存都被灭掉了。

所以,若是通过setContentView 来达到画面切换目的的,要注意重新绘制以后重新取得引用

二,getViewById的上下文对象不匹配

这种方式让笔者想到Javascript中的document.getElementById,两者具有非常高的相似性,getElementById的调用需要指定对应的document对象,表示从该document对象获取元素,同理,Android中的getViewById的完整调用是View.getViewById,因此需要关注该方法默认的context对象,一般是this,即当前的Activity,但有时候可能不是这样,如:

userDialog=newDialog(addevent.this);

userDialog.setContentView(R.layout.user_list);

userDialog.setTitle("请选择");

ListView lv=(ListView)userDialog.findViewById(R.id.userList);

lv.setAdapter(newMyAdapter());

userDialog.show();

如上,实例化lv时必须指定userDialog.findViewById()而不能直接findViewById(),,否则就会从Activity而不是Dialog的布局文件中找R.id.userList,此时当然会返回null,执行lv.setAdapter(newMyAdapter());时就会出现NullPointException异常

三,开发工具Eclipse导致的问题

假定在自定的Adapter的getView方法中有类似如下的代码:

View rowview = (View)inflater.inflate(R.layout.rowview, parent, false);

TextView tv_contact_id =(TextView)rowview.findViewById(R.id.tv_contact_id);

TextView tv_contactname =(TextView)rowview.findViewById(R.id.tv_contactname);

有时候居然也会发现rowview非空,但tv_contact_id和tv_contactname都是null!仔细看代码,怎么也看不出错误来。到底是什么原因造成的呢?答案是Eclipse造成的,要解决这个问题,需要这个项目clean一次(Project菜单 -> Clean子菜单),这样就OK了。

四,新版本SDK不能在onCreate方法中调用了-笔者的问题原因在此。

重要的环境交代:刚学Android,在官网下载的新版的ADT以及新版的SDK在新版的IDE(ADT)创建项目时如果你的最小版本(minimumrequiredSDK)要支持4.0以下版,并且目标版本为(4.0+),那么此时IDE会为你创建一个兼容包(appcompat_v7)创建项目后,这个时候在生成的项目主Activity不是以前的那种继承的Activity,而是继承的ActionBarActivity。

然后拍一些美得想哭的照片,留给老年的自己。

Android开发:getViewById返回null的原因定位

相关文章:

你感兴趣的文章:

标签云: