一.自定义控件 findViewById返回为null

首先讲一个具体的问题,这几天在做demo时,写了一个自定义组合控件,最后在run的时候显示这两行报错。原先还以为是setOnClickListener错了,后来经过debug才发现findViewById查找我的自定义组合控件为null !

debug结果:


接下来就开始了我痛苦的找bug过程,关于这段血泪过程,来总结一下findViewById 返回为空的出错原因。

首先回忆一下如何写一个自定义组合控件:

  1. 将组合控件的布局,抽取到单独的一个xml
  2. 通过一个单独的类,去加载此段布局文件.


步骤并不复杂,可是这里却有三个出错点!

1. 当你在使用自定义的组合控件时,在xml文件中使用该控件时,不能简单的写类名,包名也要!

    <com.gym.mobile.view.SettingItemView
android:id="@+id/siv_update"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
 

而不能简单的写一个:

 <SettingItemView
android:id="@+id/siv_update"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
 

2.【重点!】我们再写单独类时,必定会继承某个类,要继承它的构造方法,一定要注意,下面讲解一下这3个构造方法:

  //使用在java代码创建控件(无法加载XML文件中定义的控件属性)
public FocusTextView(Context context) {
super(context);
} //由系统调用(上下文环境构造方法 + 带属性)
public FocusTextView(Context context, AttributeSet attrs) {
super(context, attrs);
} //由系统调用(上下文环境构造方法 + 带属性 + 布局文件中定义样式文件构造方法)
public FocusTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}

这里继承的3种构造方法super调用父类一定要仔细对应!大部分错误都是出现在这里,而且在写自定义控件如果涉及到自定义属性时,一定要继承第二个构造方法!还涉及到样式,则第三个构造方法也要写!!

(而我的demo错误就是在写构造方法时,super调用父类构造函数时对应的参数有误,导致findViewById 返回为null,花了好长时间 :(


3.如果还运用到自定义属性的话,一定要在运用属性的控件内添加该项目的xmlns

xmlns:mobilesafe="http://schemas.android.com/apk/res/com.gym.mobile"
 
<com.gym.mobile.view.SettingItemView
xmlns:mobilesafe="http://schemas.android.com/apk/res/com.gym.mobile" android:id="@+id/siv_update"
android:layout_width="match_parent"
android:layout_height="wrap_content"
mobilesafe:destitle="自动更新设置"
mobilesafe:desoff="自动更新已关闭"
mobilesafe:deson="自动更新已开启">
</com.itheima.mobilesafe74.view.SettingItemView>
 




二. findViewById 返回为null

以上讨论的是一个特殊情况即自定义控件时,下面从整体分析findViewById 返回为null的情况,我们先好好思考findViewById的使用:

   findViewById的完整写法是View.findViewById(),而不指定View时默认的是Context,因此当findViewById不是在context里执行时,要指定对应的View!

   实例化控件时必须指定XXX.findViewById()而不能直接findViewById(),否则就会从Activity而不是特定的某个布局文件中找R.id.XXX

当然,如果findviewbuid之前加载了对应的布局,即可不必在findViewById之前写对应的view  !!!

关于以上这段话,也有几个出错点!

1.可能性最大的一种,也是很粗心的一种,你在加载视图的操作之前使用了findViewById寻找控件Id !试问视图都没有加载出来,控件id是找不到的。
试图加载即:

 setContentView(R.layout.activity_splash);

(以下为错误示范。。。)




2.还有一种可能性,错误很隐蔽!也是关于加载视图的问题,在寻找控件时,控件所处的xml文件要与加载的视图相同,否则setContentView中加载的视图与你需要寻找控件所处的视图不同,两个毫不相关的视图,怎么联系到一块?所以跟一开始思考findViewById那段话一样,你需要在使用findViewById之前加上相应控件所处的视图


【!!!】最典型的情况就是你在使用了 inflate特定的xml转换成view之后,再使用findViewById找view里的控件是找不到的!,因为它这里默认的是 this.findViewById(R.id.bt_submit),
所以你需要将其改为view.findViewById(R.id.bt_submit)

错误示范:

正确改法!:

最新文章

  1. JavaWeb_day03_员工信息添加修改删除
  2. php面向对象面试题
  3. 利用android来赚钱
  4. Windows 下的.NET+ Memcached安装
  5. M公司面试
  6. 【BZOJ】【1004】【HNOI2008】Cards
  7. IOS开发-- NScoding 序列化
  8. 最新 Arduino 驱动 12接口/户外 LED显示屏/LED点阵屏/LED单元板
  9. mysql 运行sql脚本文件
  10. python学习笔记(一)元组,序列,字典
  11. 转:Google技术开发指南:给大学生自学的建议
  12. ruby gems安装镜像
  13. 第07讲- Android项目的打包apk
  14. java 数组与集合(list)相互转化
  15. JS判断类型
  16. linux VPS服务器的一些配置
  17. 转:// 再说 Oracle RAC services
  18. art 校准时设备端操作
  19. php 中 &quot;&gt;&gt;&quot; &quot;&lt;&lt;&quot; 的含义
  20. 顺平讲try catch finally throw throws(精华)

热门文章

  1. 使用sqlparse分析SQL语句,及自己写的SQL分析语句
  2. 微信小程序踩坑之一【weui-wxss-master单选按钮图标修改思路】
  3. luogu P2831 愤怒的小鸟
  4. Hibernate注解详解
  5. Maven plugin提示错误“Plugin execution not covered by lifecycle configuration”
  6. Android Design Support Library概览
  7. 杂谈之WEB前端project师身价
  8. C++静态库与动态库深入研究
  9. WinDbg加载不同版本CLR
  10. 笔记08 WPF导航