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
  • 相关阅读:
    Maven关于web.xml中Servlet和Servlet映射的问题
    intellij idea的Maven项目运行报程序包找不到的错误
    修改Maven项目默认JDK版本
    刷题15. 3Sum
    刷题11. Container With Most Water
    刷题10. Regular Expression Matching
    刷题5. Longest Palindromic Substring
    刷题4. Median of Two Sorted Arrays
    刷题3. Longest Substring Without Repeating Characters
    刷题2. Add Two Numbers
  • 原文地址:https://www.cnblogs.com/the-wang/p/9016041.html
Copyright © 2011-2022 走看看