ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Drawable的mutate方法Android 1.6中的NullPointerException

2019-07-23 21:27:42  阅读:318  来源: 互联网

标签:android selector state drawable nullpointerexception


当在Android 1.6上使用带有列表状态Drawable的mutate时,我总是得到一个空指针异常.它在更高的Android版本上完美运行.我使用默认的android list_selector_background作为drawable来变异,我需要改变它,否则按下背景会变得非常混乱 – >当按下一个或多个时,它们中的全部或部分都会突出显示.

该项目在这里:

http://code.google.com/p/tree-view-list-android/

相关的一段代码在这里:http://code.google.com/p/tree-view-list-android/source/browse/src/pl/polidea/treeview/AbstractTreeViewAdapter.java#205

return activity.getResources()
                    .getDrawable(android.R.drawable.list_selector_background)
                    .mutate();

堆栈跟踪如下:

3-11 11:37:39.973: ERROR/AndroidRuntime(5304): java.lang.NullPointerException
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.graphics.drawable.StateListDrawable.mutate(StateListDrawable.java:227)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at pl.polidea.treeview.AbstractTreeViewAdapter.getDrawableOrDefaultBackground(AbstractTreeViewAdapter.java:201)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at pl.polidea.treeview.AbstractTreeViewAdapter.populateTreeItem(AbstractTreeViewAdapter.java:210)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at pl.polidea.treeview.AbstractTreeViewAdapter.getView(AbstractTreeViewAdapter.java:153)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.widget.AbsListView.obtainView(AbsListView.java:1273)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.widget.ListView.makeAndAddView(ListView.java:1658)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.widget.ListView.fillDown(ListView.java:637)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.widget.ListView.fillFromTop(ListView.java:694)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.widget.ListView.layoutChildren(ListView.java:1516)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.widget.AbsListView.onLayout(AbsListView.java:1112)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.view.View.layout(View.java:6569)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.widget.LinearLayout.layoutVertical(LinearLayout.java:998)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.widget.LinearLayout.onLayout(LinearLayout.java:918)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.view.View.layout(View.java:6569)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.view.View.layout(View.java:6569)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.widget.LinearLayout.layoutVertical(LinearLayout.java:998)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.widget.LinearLayout.onLayout(LinearLayout.java:918)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.view.View.layout(View.java:6569)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.view.View.layout(View.java:6569)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.view.ViewRoot.performTraversals(ViewRoot.java:979)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1613)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.os.Handler.dispatchMessage(Handler.java:99)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.os.Looper.loop(Looper.java:123)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at android.app.ActivityThread.main(ActivityThread.java:4203)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at java.lang.reflect.Method.invokeNative(Native Method)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at java.lang.reflect.Method.invoke(Method.java:521)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
03-11 11:37:39.973: ERROR/AndroidRuntime(5304):     at dalvik.system.NativeStart.main(Native Method)

解决方法:

似乎Android 1.6中存在一个错误.当您深入了解Android 1.6源代码时,您可以找到以下代码:

android.graphics.drawable.StateListDrawable.java:
...
public Drawable mutate() {
    if (!mMutated && super.mutate() == this) {
        final int[][] sets = mStateListState.mStateSets;
        final int count = sets.length;
        mStateListState.mStateSets = new int[count][];
        for (int i = 0; i < count; i++) {
            mStateListState.mStateSets[i] = sets[i].clone(); //NPE causing line
        }
        mMutated = true;
    }
    return this;
}
...

排队

mStateListState.mStateSets[i] = sets[i].clone(); //NPE causing line

clone() method is sometimes called on null object and it causes NullPointerException

在Android> 1.6
它已被修复:

public Drawable mutate() {
        if (!mMutated && super.mutate() == this) {
            final int[][] sets = mStateListState.mStateSets;
            final int count = sets.length;
            mStateListState.mStateSets = new int[count][];
            for (int i = 0; i < count; i++) {
                final int[] set = sets[i];
                if (set != null) {
                    mStateListState.mStateSets[i] = set.clone();
                }
            }
            mMutated = true;
        }
        return this;
    }

但在Android 1.6中我们需要做一些解决方法.让我们看看为什么mStateSets [i]有时包含空值:

android.graphics.drawable.DrawableContainer.DrowableContainerState:
... 
public final int addChild(Drawable dr) {
        final int pos = mNumChildren;

        if (pos >= mDrawables.length) {
            growArray(pos, pos+10); //Interesting line
        }

        dr.setVisible(false, true);
        dr.setCallback(mOwner);

        mDrawables[pos] = dr;
        mNumChildren++;
        mChildrenChangingConfigurations |= dr.getChangingConfigurations();
        mHaveOpacity = false;
        mHaveStateful = false;

        mConstantPadding = null;
        mPaddingChecked = false;
        mComputedConstantSize = false;

        return pos;
    }
...

在从xml膨胀对象期间调用上面的方法.所以mStateListState.mStateSets的大小是N * 10.

现在让我们看看你试图从android.R.drawable.list_selector_background引用的资源中膨胀的list_selector_background.xml的主体:

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 The Android Open Source Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_window_focused="false"
        android:drawable="@color/transparent" />

    <!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
    <item android:state_focused="true" android:state_enabled="false"
        android:state_pressed="true"
        android:drawable="@drawable/list_selector_background_disabled" />
    <item android:state_focused="true" android:state_enabled="false"
        android:drawable="@drawable/list_selector_background_disabled" />

    <item android:state_focused="true" android:state_pressed="true"
        android:drawable="@drawable/list_selector_background_transition" />
    <item android:state_focused="false" android:state_pressed="true"
        android:drawable="@drawable/list_selector_background_transition" />

    <item android:state_focused="true"
        android:drawable="@drawable/list_selector_background_focus" />

</selector>

此文件仅包含6个项目!
那么我们如何解决这个问题呢?
1.在{Project} / res / drowable /中创建list_selector_background.xml,您可以复制Android one并只更改一行:

<item android:state_window_focused="false"
    android:drawable="@color/transparent" />

<item android:state_window_focused="false" android:drawable="@android:color/transparent" />

>复制Android或创建自己的文件:

list_selector_background_disabled.9.png
list_selector_background_focus.9.png
list_selector_background_longpress.9.png
list_selector_background_pressed.9.png
list_selector_background_transition.xml
>修改list_selector_background.xml添加虚拟项目以完全匹配(6 4 = 10)个项目condidtion:

<item android:animationCache="true"
    android:drawable="@android:color/transparent" />

<item android:animationCache="false"
    android:drawable="@android:color/transparent" />

<item android:alwaysDrawnWithCache="false"
    android:drawable="@android:color/transparent" />

<item android:alwaysDrawnWithCache="true"
    android:drawable="@android:color/transparent" />

瞧.编译并运行.它现在应该工作.

标签:android,selector,state,drawable,nullpointerexception
来源: https://codeday.me/bug/20190723/1516693.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有