2011-03-11 111 views
3

在Android 1.6上使用列表狀態的mutate時可繪製我總是有一個空指針異常。它可以在更高版本的Android上完美運行。我使用默認的android list_selector_background作爲可變更的drawable,並且我需要對它進行變異,否則被按下的背景變得非常混亂 - >當按下時,所有或部分變得更加突出。Drawable的mutate方法中的NullPointerException Android 1.6

該項目是在這裏:

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) 

回答

9

它似乎有一個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()方法有時也稱爲空物體上,它會導致空指針異常

in 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。

現在讓我們看看list_selector_background.xml的身體,你正試圖從資源利用爲參照,以android.R.drawable.list_selector_background膨脹:

<?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.創建(項目)/ RES/drowable /你可以複製Android的一個,改變只有一行list_selector_background.xml:

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

<item android:state_window_focused="false" android:drawable="@android:color/transparent" /> 
  1. 複製Android或創建自己的文件:

    list_selector_background_disabled.9.png list_selector_background_focus.9.png list_selector_background_longpres s.9.png list_selector_background_pressed.9.png list_selector_background_transition.xml

  2. 修改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" /> 
    

瞧。編譯並運行。它現在應該工作。

+0

工程就像一個魅力:)。 – 2011-03-13 11:08:36

+0

也發生在一些Eclair設備(LG GT540)上。您的修復程序有幫 – Thorstenvv 2012-02-02 14:55:17

相關問題