web-dev-qa-db-fra.com

Crash dans ListView sur AbsListView.obtainView pour ListActivity

J'observe les mises à jour de contenu sur une ListActivity à l'aide d'un ContentObserver comme suit:

protected void onCreate(Bundle savedState)
   {
        super.onCreate(savedState);

        ContentResolver cr = getContentResolver();

        Cursor cursor = cr.query(TrackHeader.CONTENT_URI, sTrackListProjection, null, null, null);
        startManagingCursor(cursor);

        this.mAdapter = new TrackHeaderDataAdapter(this, R.layout.track_list_item, cursor, sTrackListProjection, null);
        setListAdapter(mAdapter);

        Handler handler = new Handler();

        mTrackHeaderObserver = new ContentObserver(handler) {

             @Override 
             public boolean deliverSelfNotifications() { 
                 return false;
             }

             @Override
             public void onChange(boolean selfChange) {
                 super.onChange(selfChange);
                 ContentResolver cr = getContentResolver();
                 mAdapter.changeCursor(cr.query(TrackHeader.CONTENT_URI, sTrackListProjection, null, null, null));
              }
         };

      getContentResolver().registerContentObserver (TrackHeader.CONTENT_URI, true, mTrackHeaderObserver);
  }

Cet observateur de contenu semble être correct - il est rappelé sur le thread d'interface utilisateur, mais je reçois le crash aléatoire suivant de manière assez prévisible sur le ListView sous-jacent:

02-21 14:06:00.440: ERROR/AndroidRuntime(739): Java.lang.NullPointerException
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at  Android.widget.AbsListView.obtainView(AbsListView.Java:1276)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.widget.ListView.makeAndAddView(ListView.Java:1668)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.widget.ListView.fillDown(ListView.Java:637)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.widget.ListView.fillSpecific(ListView.Java:1224)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.widget.ListView.layoutChildren(ListView.Java:1499)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.widget.AbsListView.onLayout(AbsListView.Java:1113)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.view.View.layout(View.Java:6830)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.widget.FrameLayout.onLayout(FrameLayout.Java:333)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.view.View.layout(View.Java:6830)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.widget.FrameLayout.onLayout(FrameLayout.Java:333)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.view.View.layout(View.Java:6830)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.widget.FrameLayout.onLayout(FrameLayout.Java:333)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.view.View.layout(View.Java:6830)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.widget.LinearLayout.setChildFrame(LinearLayout.Java:1119)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.widget.LinearLayout.layoutVertical(LinearLayout.Java:998)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.widget.LinearLayout.onLayout(LinearLayout.Java:918)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.view.View.layout(View.Java:6830)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.widget.FrameLayout.onLayout(FrameLayout.Java:333)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.view.View.layout(View.Java:6830)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.widget.FrameLayout.onLayout(FrameLayout.Java:333)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.view.View.layout(View.Java:6830)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.widget.FrameLayout.onLayout(FrameLayout.Java:333)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.view.View.layout(View.Java:6830)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.view.ViewRoot.performTraversals(ViewRoot.Java:996)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.view.ViewRoot.handleMessage(ViewRoot.Java:1633)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.os.Handler.dispatchMessage(Handler.Java:99)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.os.Looper.loop(Looper.Java:123)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Android.app.ActivityThread.main(ActivityThread.Java:4363)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Java.lang.reflect.Method.invokeNative(Native Method)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at Java.lang.reflect.Method.invoke(Method.Java:521)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:860)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:618)
02-21 14:06:00.440: ERROR/AndroidRuntime(739):     at dalvik.system.NativeStart.main(Native Method)
02-21 14:09:56.159: ERROR/AndroidRuntime(749): ERROR: thread attach failed
02-21 14:09:59.480: ERROR/AndroidRuntime(760): ERROR: thread attach failed
02-21 14:12:19.449: ERROR/AndroidRuntime(778): ERROR: thread attach failed
02-21 14:12:22.779: ERROR/AndroidRuntime(789): ERROR: thread attach failed
02-21 14:12:26.479: ERROR/gralloc(51): [unregister] handle 0x3f13b8 still locked (state=40000001)

Quiconque a déjà vu quelque chose comme ça auparavant - a été bloqué sur celui-ci pendant quelques jours ...

Tim

56
Tim

J'avais une trace de pile similaire et j'ai découvert que je retournais un null de ma méthode getView () dans certains cas.

229
jonny99

Si vous avez une liste et étendez BaseAdapter ou Adapter pour obtenir une liste personnalisée, assurez-vous que getView renvoie une valeur non nulle.

Si vous avez une vue à onglets et l'un de vos fragments est une liste qui remplace Adapter/BaseAdapter et getView renvoie null, vous obtiendrez ce problème.

11
Skywalker

Si vous utilisez une classe statique ViewHolder pour stocker vos éléments de vue dans l'adaptateur, vous pouvez oublier de définir l'objet viewHolder comme balise de convertView. Par exemple:

if (convertView == null) {
    LayoutInflater mInflater = (LayoutInflater) context
                .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        convertView = mInflater.inflate(R.layout.adapter_drivers_and_riders, null);
        holder = new ViewHolder();
        holder.tvDate = (TextView)convertView.findViewById(R.id.tvDate);
        holder.tvTime = (TextView)convertView.findViewById(R.id.tvTime);

        convertView.setTag(holder);

} else {
    holder = (ViewHolder) convertView.getTag();
}

Dans mon cas, je n'utilisais pas de curseur mais ayant le même problème, je me suis rendu compte que j'avais oublié de définir la balise comme viewHolder pour convertirView, donc lorsque les premières vues d'adaptateur sont créées pour la liste, c'est correct mais lorsque vous faites défiler et le mécanisme de recyclage fonctionne, il se bloque car il ne peut pas restaurer le viewHolder de convertView.

Au cas où, je voulais le mentionner.

4
Merve Gencer

Je n'ai pas utilisé changeCursor(). Et, puisque la requête que vous avez utilisée pour créer le Cursor est la même que la requête que vous utilisez pour "changer" le curseur, je viderais l'appel de changeCursor() tout de suite et j'appellerais simplement requery() sur le Cursor que vous avez.

3
CommonsWare