zoukankan      html  css  js  c++  java
  • (转)findViewById 返回为null (自定义控件)

    一.自定义控件 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)

    错误示范:
    这里写图片描述

    正确改法!:

    这里写图片描述

    转载自:转载注明:http://blog.csdn.net/itermeng/article/details/52034186
  • 相关阅读:
    【iOS 实践笔记】UITableView顶部空白
    【iOS入门】dequeueReusableCellWithIdentifier:和dequeueReusableCellWithIdentifier:forIndexPath:的区别
    【iOS 入门】@class关键字
    【iOS 入门 动画学习】
    【android seekbar 增大拖动区域】
    【android 动画小技巧】一个控制顺序播放多个动画。
    【android 视频播放那些事之缓存】
    【java8 代码块新功能】
    Mac下使用gradlew命令
    Python格式符说明
  • 原文地址:https://www.cnblogs.com/the-wang/p/9016041.html
Copyright © 2011-2022 走看看