近期在研究开发一些基于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=new Dialog(addevent.this);

userDialog.setContentView(R.layout.user_list);

userDialog.setTitle("请选择");

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

lv.setAdapter(new MyAdapter());

userDialog.show();

如上,实例化lv时必须指定userDialog.findViewById()而不能直接findViewById()。否则就会从Activity而不是Dialog的布局文件里找R.id.userList,此时当然会返回null,运行lv.setAdapter(new MyAdapter());时就会出现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。

此时,假设你仍然用旧的办法在onCreate调用getViewById,那么会返回null,原因是:在新的layout文件不是存放在默认的(res/layout/activity_quiz.xml)文件里,而是存放在(res/layout/fragment_quiz.xml)文件里。所以要在fragment_quiz.xml去找相应的ID才会找到,而新的IDE生成的代码中载入(fragment_quiz.xml)文件是在一个内部类载入的,所以一种方法是:我们能够在内部类载入处来得到Button。

/**

* A placeholder fragment containing a simple view.

*/

public static class PlaceholderFragment extends Fragment {

View rootView = null;

public PlaceholderFragment() {

}

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,

Bundle savedInstanceState) {

rootView = inflater.inflate(R.layout.fragment_quiz, container, false);

mTrueButton = (Button) rootView.findViewById(R.id.true_button);

System.out.println(button);

return rootView;

}

}

第二种方法是:假设熟悉Activity的生命周期的人能够知道:onCreate调用的时候事实上还没构造相应的布局对象,因此不能在onCreate函数中获取控件。但能够在onStart函数中获取:(笔者的方案就是在onStart方法中获取的)



@Override

protected void onStart() {

      super.onStart();

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

      mTrueButton.setOnClickListener(new android.view.View.OnClickListener(){

          public void onClick(android.view.View v) {

             
//TODO...

          }

      });

}

Android开发:getViewById返回null的原因定位的更多相关文章

  1. Android GsmCellLocation.getCellLocation返回NULL

    Android GsmCellLocation.getCellLocation返回NULL 1.首先 获取服务 telephonyManager =(TelephonyManager)getSyste ...

  2. Android Fragment getActivity返回null解决

    在Android开发中,如果我们用到V4包里面的Fragment,在应用被切换到后台的时候,Activity可能被回收,但是创建的所有Fragment则会被保存到Bundle里面,下面是Fragmen ...

  3. Android开发:LocationManager获取经纬度及定位过程(附demo)

    在Android开发其中.常常须要用到定位功能,尤其是依赖于地理位置功能的应用.非常多人喜欢使用百度地图,高德地图提供的sdk.开放API,可是在只须要经纬度,或者城市,街道地址等信息.并不须要提供预 ...

  4. fopen() 返回 NULL, 奇葩原因:当前进程打开多个句柄,忘记关闭。(bug)

    今天在测试一个程序的时候,突然第一次弹出错误对话框,提示: 创建新文件失败. fopen() 返回 NULL 我又重启程序测试,还是提示同样的错误. 经过几分钟的检查,发现一个规律:当处理到500多个 ...

  5. PHP解码Json(json_decode)字符串返回NULL的原因及解决方法(转载)

    本文主要为大家讲解了php在使用json_decode函数解码json字符串时,解码不成功返回NULL的问题原因分析和解决方法,感兴趣的同学参考下. 一般来说,php对json字符串解码使用json_ ...

  6. Android 开发之集成百度地图的定位与地图展示

    app 应用中,大多数应用都具有定位功能,百度定位就成了开发人员的集成定位功能的首选,近期也在做定位功能,可是发现百度真是个大坑啊, sdk 命名更新了,相关代码却不更新,害得我花费了非常长时间来研究 ...

  7. Android fragment-findFragmentByTag 始终返回 null

    我曾四处看看,在我的案子中找到几个与类似的主题,但没有帮助的问题.我想访问现有活动片段使用getSupportFragmentManager().findFragmentByTag(TAG),但它始终 ...

  8. Android开发 更改返回button的图标

    非常多的Android应用左上角都有返回button 在默认的情况下 ADT会默认给一个返回图标 而作为开发需求 非常多都要求定制一个新的图标 在Android的站点上 发现了2种能够更改的方法 1. ...

  9. [Android Pro] Android Fragment getActivity返回null解决

    overide FragmentActivity  onSaveInstanceState method like this. @Override public void onSaveInstance ...

随机推荐

  1. java中的hachcode方法

    哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int hashCode(); 根据这个 ...

  2. HDU 4336

    概率DP期望,逆推即可.使用状态压缩. 注意,要全部输出...看DIS才发现题目输出是个坑.. #include <iostream> #include <cstdio> #i ...

  3. 【转载】黑客内核:编写属于你的第一个Linux内核模块

    黑客内核:编写属于你的第一个Linux内核模块

  4. 排序(3)---------冒泡排序(C语言实现)

    说到冒泡排序,大一的时候第一次学习这个排序算法,可能大家不知道,"冒泡"在我说的方言里面是吹牛逼的意思. 所以就认为这个排序算法特吹牛逼有木有. 相信大家对全部的排序算法,这个想必 ...

  5. hdu1281 棋盘游戏 --- 最大匹配

    给一个矩形棋盘,上面有一些空格点,能够放象棋中的"车", 现给出空格的坐标,求最多能够放多少个"车"使他们互不攻击(依据象棋规则,每行每列至多仅仅能放一个), ...

  6. struts2请求过程源代码分析

    struts2请求过程源代码分析 Struts2是Struts社区和WebWork社区的共同成果.我们甚至能够说,Struts2是WebWork的升级版.他採用的正是WebWork的核心,所以.Str ...

  7. Sambaserver搭建

    1. 安装Samba及相关包 $ sudo apt-getinstall samba samba-common smbfspython-glade2system-config-samba 2. 创建共 ...

  8. node18---Mongoose

    二.索引index 数据库中,根据一个字段的值,来寻找一个文档,是很常见的操作.比如根据学号来找一个学生. 这个学号,是唯一的,只要有学号,就能唯一确认一个学生的文档.学号这个属性,就非常适合建立索引 ...

  9. JAVA设计模式之【策略模式】

    策略模式 定义一些独立的类来封装不同的算法 类似于common方法或者引用类 角色 环境类Context 抽象策略Strategy 具体策略ConcreteStrategy 重构伴随着设计模式 重构类 ...

  10. pyspark kafka createDirectStream和createStream 区别

    from pyspark.streaming.kafka import KafkaUtils kafkaStream = KafkaUtils.createStream(streamingContex ...