2011-03-11 6 views
3

Lors de l'utilisation de muter sur Android 1.6 avec l'état de la liste Drawable j'ai toujours eu une exception de pointeur nul. Il fonctionne parfaitement sur les versions supérieures d'Android. J'utilise le android list_selector_background par défaut comme monnayable, et j'ai besoin de le faire muter, sinon les arrière-plans pressés deviendront plutôt désordonnés -> tous ou certains d'entre eux sont surlignés quand on appuie dessus.NullPointerException dans la méthode mute de Drawable Android 1.6

Le projet est ici:

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

et la pièce correspondante de code ici: 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(); 

Trace de la pile ci-dessous:

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) 

Répondre

9

Il semble qu'il y ait un bug dans Android 1.6. Lorsque vous plonger dans Android 1.6 sources vous pouvez trouver le code suivant:

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; 
} 
... 

en ligne

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

clone() est parfois appelé objet nul et il provoque NullPointerException

dans Android> 1.6 il a été corrigé:

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; 
    } 

mais dans Android 1.6, nous devons faire une solution de contournement. Voyons pourquoi mStateSets [i] contient parfois des valeurs nulles:

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; 
    } 
... 

ci-dessus méthode est appelée lors de l'objet de gonfler xml. La taille de mStateListState.mStateSets est donc N * 10.

Maintenant, nous allons voir le corps de list_selector_background.xml que vous essayez de gonfler des ressources par android.R.drawable.list_selector_background référent:

<?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> 

ce fichier contient seulement 6 articles! Alors, comment pouvons-nous résoudre le problème? 1. Créez list_selector_background.xml dans {} Projet/res/drowable/vous pouvez copier un Android et changer une seule ligne:

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

à

<item android:state_window_focused="false" android:drawable="@android:color/transparent" /> 
  1. Copier Android ou créer votre propre fichiers:

    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. Modifier list_selector_background.xml ajout d'éléments factices pour correspondre exactement (6 + 4 = 10) éléments 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" /> 
    

Voilà. Compiler et exécuter. Cela devrait fonctionner maintenant.

+0

Fonctionne comme un charme :). –

+0

arrive également sur certains appareils Eclair (LG GT540). Votre réparation aide. – Thorstenvv

Questions connexes