View标签与view标签引发的bug思考

题引:前些天想用View标签写个下划线,结果把View写成view了,出现了一个奇葩的bug。
  • bug堆栈
  • bug分析
  • 源码分析
一、bug堆栈
03-09 15:35:28.654 29199-29199/com.jiudaifu.yangsheng E/AndroidRuntime: FATAL EXCEPTION: main
                                                                        Process: com.jiudaifu.yangsheng, PID: 29199
                                                                        **java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference** at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:734)
                                                                            at android.view.LayoutInflater.rInflate(LayoutInflater.java:825)
                                                                            at android.view.LayoutInflater.rInflate(LayoutInflater.java:828)
                                                                            at android.view.LayoutInflater.inflate(LayoutInflater.java:523)
                                                                            at android.view.LayoutInflater.inflate(LayoutInflater.java:425)
                                                                            at android.view.LayoutInflater.inflate(LayoutInflater.java:368)
                                                                            at com.jiudaifu.yangsheng.adapter.CaseListAdapter.getView(CaseListAdapter.java:51)
                                                                            at android.widget.AbsListView.obtainView(AbsListView.java:2369)
                                                                            at android.widget.ListView.measureHeightOfChildren(ListView.java:1274)
                                                                            at android.widget.ListView.onMeasure(ListView.java:1186)
                                                                            at android.view.View.measure(View.java:17628)
                                                                            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5548)
                                                                            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1467)
                                                                            at android.widget.LinearLayout.measureVertical(LinearLayout.java:747)
                                                                            at android.widget.LinearLayout.onMeasure(LinearLayout.java:638)
                                                                            at android.view.View.measure(View.java:17628)
                                                                            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5548)
                                                                            at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
                                                                            at android.view.View.measure(View.java:17628)
                                                                            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5548)
                                                                            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1467)
                                                                            at android.widget.LinearLayout.measureVertical(LinearLayout.java:747)
                                                                            at android.widget.LinearLayout.onMeasure(LinearLayout.java:638)
                                                                            at android.view.View.measure(View.java:17628)
                                                                            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5548)
                                                                            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1467)
                                                                            at android.widget.LinearLayout.measureVertical(LinearLayout.java:747)
                                                                            at android.widget.LinearLayout.onMeasure(LinearLayout.java:638)
                                                                            at android.view.View.measure(View.java:17628)
                                                                            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5548)
                                                                            at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
                                                                            at android.view.View.measure(View.java:17628)
                                                                            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5548)
                                                                            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1467)
                                                                            at android.widget.LinearLayout.measureVertical(LinearLayout.java:747)
                                                                            at android.widget.LinearLayout.onMeasure(LinearLayout.java:638)
                                                                            at android.view.View.measure(View.java:17628)
                                                                            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5548)
                                                                            at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
                                                                            at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2639)
                                                                            at android.view.View.measure(View.java:17628)
                                                                            at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2081)
                                                                            at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1217)
                                                                            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1423)
                                                                            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1105)
                                                                            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6204)
                                                                            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:799)
                                                                            at android.view.Choreographer.doCallbacks(Choreographer.java:612)
                                                                            at android.view.Choreographer.doFrame(Choreographer.java:581)
                                                                            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:785)
                                                                            at android.os.Handler.handleCallback(Handler.java:739)
                                                                            at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                            at android.os.Looper.loop(Looper.java:135)
                                                                            at android.app.ActivityThread.main(ActivityThread.java:5669)
                                                                            at java.lang.reflect.Method.invoke(Native Method)
                                                                            at java.lang.reflect.Method.invoke(Method.java:372)
                                                                            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:960)
                                                                            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
03-09 15:35:28.964 29199-29199/com.jiudaifu.yangsheng I/Process: Sending signal. PID: 29199 SIG: 9
二、bug分析
1、bug:在一个空指针上调用equals()方法。
2、事实上,我没调用过equals()这个方法。
3、跟进Android源码,发现是Android源码调用equals()方法报空指针异常。
涉及的Android源码如下:
View createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
            boolean ignoreThemeAttr) {
        if (name.equals("view")) {
            name = attrs.getAttributeValue(null, "class");
        }


        // Apply a theme wrapper, if allowed and one is specified.
        if (!ignoreThemeAttr) {
            final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);
            final int themeResId = ta.getResourceId(0, 0);
            if (themeResId != 0) {
                context = new ContextThemeWrapper(context, themeResId);
            }
            ta.recycle();
        }


        if (name.equals(TAG_1995)) {
            // Let's party like it's 1995!
            return new BlinkLayout(context, attrs);
        }


        try {
            View view;
            if (mFactory2 != null) {
                view = mFactory2.onCreateView(parent, name, context, attrs);
            } else if (mFactory != null) {
                view = mFactory.onCreateView(name, context, attrs);
            } else {
                view = null;
            }


            if (view == null && mPrivateFactory != null) {
                view = mPrivateFactory.onCreateView(parent, name, context, attrs);
            }


            if (view == null) {
                final Object lastContext = mConstructorArgs[0];
                mConstructorArgs[0] = context;
                try {
                    if (-1 == name.indexOf('.')) {
                        view = onCreateView(parent, name, attrs);
                    } else {
                        view = createView(name, null, attrs);
                    }
                } finally {
                    mConstructorArgs[0] = lastContext;
                }
            }


            return view;
        } catch (InflateException e) {
            throw e;


        } catch (ClassNotFoundException e) {
            final InflateException ie = new InflateException(attrs.getPositionDescription()
                    + ": Error inflating class " + name);
            ie.initCause(e);
            throw ie;


        } catch (Exception e) {
            final InflateException ie = new InflateException(attrs.getPositionDescription()
                    + ": Error inflating class " + name);
            ie.initCause(e);
            throw ie;
        }
    }
三、Android源码分析
1、Android源码通过判断标签名是View还是view来做不同逻辑处理。
2、如果是view的话就会去获取class属性的值,但是我在xml中并没有设置class属性的值,因此获取到的将会是空指针,进而执行到equals()方法时就会报空指针。
3、另外,view也是可以用作xml标签的,不过是用于在xml中引用内部类的View
参考:http://blog.csdn.net/gorgle/article/details/51428515
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值