recyclerview pullrefresh example ejemplo android android-support-library swiperefreshlayout

android - pullrefresh - swiperefreshlayout recyclerview



IllegalArgumentException: punteroIndex fuera de rango de SwipeRefreshLayout (6)

He estado recibiendo algunos de estos IllegalArgumentException: pointerIndex out of range bloquea en crashlytics y no entiendo lo que está sucediendo. No se limita a una compilación o dispositivo de Android, sucede en 5.0.1, 4.4.4, 4.4.2, 4.0.4, 2.3.6, todo en varios dispositivos. A continuación se muestra la salida de registro completo para más contexto.

java.lang.RuntimeException: Unable to destroy activity {com.mypackage.myapp/com.mypackage.myapp.MyListActivity}: java.lang.IllegalArgumentException: pointerIndex out of range at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3671) at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3689) at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3889) at android.app.ActivityThread.access$900(ActivityThread.java:144) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1284) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5221) at java.lang.reflect.Method.invoke(Method.java) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693) Caused by: java.lang.IllegalArgumentException: pointerIndex out of range at android.view.MotionEvent.nativeGetAxisValue(MotionEvent.java) at android.view.MotionEvent.getY(MotionEvent.java:1998) at android.support.v4.view.MotionEventCompatEclair.getY(MotionEventCompatEclair.java:35) at android.support.v4.view.MotionEventCompat$EclairMotionEventVersionImpl.getY(MotionEventCompat.java:95) at android.support.v4.view.MotionEventCompat.getY(MotionEventCompat.java:228) at android.support.v4.widget.SwipeRefreshLayout.onTouchEvent(SwipeRefreshLayout.java:772) at android.view.View.dispatchTouchEvent(View.java:8388) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2398) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2158) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2400) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2172) at android.view.ViewGroup.cancelTouchTarget(ViewGroup.java:2340) at android.view.ViewGroup.removeViewInternal(ViewGroup.java:4156) at android.view.ViewGroup.removeViewInternal(ViewGroup.java:4136) at android.view.ViewGroup.removeView(ViewGroup.java:4068) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1045) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1126) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1108) at android.support.v4.app.FragmentManagerImpl.dispatchDestroy(FragmentManager.java:1954) at android.support.v4.app.FragmentActivity.onDestroy(FragmentActivity.java:313) at android.support.v7.app.ActionBarActivity.onDestroy(ActionBarActivity.java:169) at com.mypackage.myapp.BaseActivity.onDestroy(BaseActivity.java:105) at android.app.Activity.performDestroy(Activity.java:6112) at android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1140) at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3658) at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3689) at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3889) at android.app.ActivityThread.access$900(ActivityThread.java:144) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1284) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5221) at java.lang.reflect.Method.invoke(Method.java) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)

Aquí hay otro informe de bloqueo relacionado que proviene de android.view.MotionEvent.getY() .

java.lang.RuntimeException: Unable to destroy activity {com.mypackage.myapp/com.mypackage.myapp.MyListActivity}: java.lang.ArrayIndexOutOfBoundsException at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:2683) at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:2701) at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:2817) at android.app.ActivityThread.access$1600(ActivityThread.java:117) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:946) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:130) at android.app.ActivityThread.main(ActivityThread.java:3733) at java.lang.reflect.Method.invokeNative(Method.java) at java.lang.reflect.Method.invoke(Method.java:507) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:931) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:689) at dalvik.system.NativeStart.main(NativeStart.java) Caused by: java.lang.ArrayIndexOutOfBoundsException at android.view.MotionEvent.getY(MotionEvent.java:903) at android.support.v4.view.MotionEventCompatEclair.d(MotionEventCompatEclair.java:35) at android.support.v4.view.MotionEventCompat$EclairMotionEventVersionImpl.d(MotionEventCompat.java:95) at android.support.v4.view.MotionEventCompat.d(MotionEventCompat.java:228) at android.support.v4.widget.SwipeRefreshLayout.onTouchEvent(SwipeRefreshLayout.java:772) at android.view.View.dispatchTouchEvent(View.java:3971) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:903) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1154) at android.view.ViewGroup.removeViewInternal(ViewGroup.java:2201) at android.view.ViewGroup.removeViewInternal(ViewGroup.java:2187) at android.view.ViewGroup.removeView(ViewGroup.java:2135) at android.support.v4.app.FragmentManagerImpl.a(FragmentManager.java:1045) at android.support.v4.app.FragmentManagerImpl.a(FragmentManager.java:1126) at android.support.v4.app.FragmentManagerImpl.a(FragmentManager.java:1108) at android.support.v4.app.FragmentManagerImpl.t(FragmentManager.java:1954) at android.support.v4.app.FragmentActivity.onDestroy(FragmentActivity.java:313) at android.support.v7.app.ActionBarActivity.onDestroy(ActionBarActivity.java:169) at com.mypackage.myapp.BaseActivity.onDestroy(BaseActivity.java:105) at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:2670) at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:2701) at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:2817) at android.app.ActivityThread.access$1600(ActivityThread.java:117) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:946) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:130) at android.app.ActivityThread.main(ActivityThread.java:3733) at java.lang.reflect.Method.invokeNative(Method.java) at java.lang.reflect.Method.invoke(Method.java:507) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:931) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:689) at dalvik.system.NativeStart.main(NativeStart.java)

Entonces, mi pregunta es ¿qué está causando este error y cuál sería el método aceptable para mitigar este problema?

EDITAR: Aquí está el enlace a MotionEvent.java:1998 que se hace referencia en el bloqueo anterior.

EDITAR: Aquí está mi onDestroy parece:

@Override public void onDestroy() { AppMsg.cancelAll(); SuperCardToast.cancelAllSuperCardToasts(); super.onDestroy(); }

Específicamente, BaseActivity.java:105 es donde llamo a super.onDestroy(); .


He visto un error similar cuando el número de elementos en un ViewPager (que extiende ViewGroup) se configuró incorrectamente. Así que la aplicación llamaría android.view.MotionEvent.getY(10) cuando había 10 (no 11) elementos en la lista. Puede intentar la depuración obteniendo el recuento de lo que está en el Grupo de vista.

También me interesaría saber qué hay dentro de su método com.mypackage.myapp.BaseActivity.onDestroy.

Además, detecté esto, aparentemente hay un error en Eclair: https://.com/a/16519902/2832027 Es posible que haya un error en Eclair que se haya solucionado, pero algunas personas no han recibido la actualización, ¿Si está funcionando bien en tu versión de Eclair?

ACTUALIZACIÓN: mirando su método onDestroy y los errores: parece que llamar a OnDestroy puede desencadenar un último evento en ViewGroup que llama en la última vista del grupo que se estaba viendo. ¿Podría AppMsg.cancelAll() o SuperCardToast.cancelAllSuperCardToasts() destruir estas vistas? ¿Podrías poner el super.onDestroy () delante de ellos en tu método onDestroy?

Sin embargo, si este es el problema, es extraño que no pueda replicarlo usted mismo. También podría ser un problema con la longitud de los usuarios de ViewGroup frente al tuyo. Si tiene ViewGroups muy cortos, ¿puede replicar el problema?

Los registros de errores que muestra solo parecen ser para Eclair, pero usted dice que el problema ocurre en todos los dispositivos. ¿Puede publicar un registro de errores para un dispositivo que no sea Eclair?


Para cualquiera que todavía esté mirando, estaba viendo esto cuando los eventos táctiles estaban en conflicto con el cajón de navegación. Agregué un cheque en el onTouch de mi actividad.

if (mNavigationDrawerFragment != null && mNavigationDrawerFragment.isDrawerOpen()) { return super.onTouchEvent(event); }

Y parece ser mejor. en NavigationDrawerFragment:

@Override public void onDrawerSlide(View drawerView, float slideOffset) { super.onDrawerSlide(drawerView, slideOffset); mIsDrawerOpen = slideOffset != 0; getActivity().invalidateOptionsMenu(); }

y devuelve mIsDrawerOpen en isDrawerOpen()


Parece que dentro del onTouchEvent de SwipeRefreshLayout se acaba de agregar la validación de puntero en ACTION_CANCEL pero no se agregó la validación de índice de puntero que está disponible para ACTION_MOVE. Así que he creado una clase personalizada para ella y la manejo para ACTION_CANCEL & ACTION_UP.

Hasta ahora todo está funcionando correctamente y pronto lanzaré una actualización de mi aplicación. Si todavía obtienes alguna excepción en crashlytics, actualizaré mi solución. Hasta ese momento Disfruta :)

La clase pública SwipeRefreshLayoutX extiende SwipeRefreshLayout {

private int mActivePointerId; public SwipeRefreshLayoutX(Context context) { super(context); // TODO Auto-generated constructor stub } public SwipeRefreshLayoutX(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } @Override public boolean onTouchEvent(MotionEvent event) { final int action = MotionEventCompat.getActionMasked(event); switch (action) { case MotionEvent.ACTION_DOWN: mActivePointerId = MotionEventCompat.getPointerId(event, 0); break; case MotionEvent.ACTION_POINTER_DOWN:{ final int index = MotionEventCompat.getActionIndex(event); mActivePointerId = MotionEventCompat.getPointerId(event, index); break; } case MotionEvent.ACTION_POINTER_UP:{ onSecondaryPointerUp(event); break; } case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL:{ final int pointerIndex = MotionEventCompat.findPointerIndex(event, mActivePointerId); if (pointerIndex < 0) { Log.e("ash", "Got ACTION_UP event but have an invalid active pointer id."); return false; } break; } } return super.onTouchEvent(event); } private void onSecondaryPointerUp(MotionEvent ev) { final int pointerIndex = MotionEventCompat.getActionIndex(ev); final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); if (pointerId == mActivePointerId) { // This was our active pointer going up. Choose a new // active pointer and adjust accordingly. final int newPointerIndex = pointerIndex == 0 ? 1 : 0; mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); } }

}


Si no ve ningún problema aparente en su aplicación, puede intentar usar una versión personalizada "silenciosa" de SwipeRefreshLayout :

public class CustomSwipeRefreshLayout extends SwipeRefreshLayout{ public CustomSwipeRefreshLayout(Context context) { super(context); } public CustomSwipeRefreshLayout(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onTouchEvent(MotionEvent event) { try{ return super.onTouchEvent(event); } catch(Exception e){ return true; } } }


Supongo que la excepción se produce cuando todavía hay un evento táctil (se transmite al toque nativo mientras la Actividad está a punto de onDestroy() . Está bien mitigar esto detectando la excepción para evitar el bloqueo. La actividad se trata de Ser destruido si ha entrado en este estado.

No estoy seguro (no lo he probado), pero podría intentar evitar que los eventos pasen a la implementación, si la excepción de captura no se ajusta a usted.

public class ComeUpWithBetterNameSwipeRefreshLayout extends SwipeRefreshLayout { private boolean mAcceptEvents; public ComeUpWithBetterNameSwipeRefreshLayout(Context context) { super(context); } public void setAcceptEvents(boolean mAcceptEvents) { this.mAcceptEvents = mAcceptEvents; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return mAcceptEvents? super.onInterceptTouchEvent(ev) : true; } public ComeUpWithBetterNameSwipeRefreshLayout(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); mAcceptEvents = true; } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); mAcceptEvents = false; } }

o

@Override public void onDestroy() { mSwipeRefreshLayout.setAcceptEvents(false); AppMsg.cancelAll(); SuperCardToast.cancelAllSuperCardToasts(); super.onDestroy(); }

Toma 2 :

SwipeRefreshLayout intenta obtenerY () desde un índice de puntero no válido, llamando a findPointerIndex(ev, activePointer) devuelve -1 si no puede encontrarlo. La prevención del evento táctil de envío con un puntero no válido menor que 0 y un índice de puntero mayor o igual que el número de punteros para ese evento probablemente evitará que la validación del puntero dentro de la implementación de MotionEvent nativa arroje IAE.

@Override public boolean onInterceptTouchEvent(MotionEvent ev) { if(ev.getAction() == MotionEvent.ACTION_CANCEL) { int pointerCount = MotionEventCompat.getPointerCount(ev); int index = MotionEventCompat.getActionIndex(ev); mActivePointerId = MotionEventCompat.getPointerId(ev, index); index = MotionEventCompat.findPointerIndex(ev,mActivePointerId); if (index > -1 && index < pointerCount) { super.onInterceptTouchEvent(ev); } else { return true; } }else if(ev.getAction() == MotionEventCompat.ACTION_POINTER_DOWN && super.onInterceptTouchEvent(ev)) { final int index = MotionEventCompat.getActionIndex(ev); mActivePointerId = MotionEventCompat.getPointerId(ev, index); return false; }else if(ev.getAction() == MotionEventCompat.ACTION_POINTER_UP && super.onInterceptTouchEvent(ev)){ onSecondaryPointerUp(ev); return false; }else if(ev.getAction() == MotionEvent.ACTION_DOWN && super.onInterceptTouchEvent(ev)){ mActivePointerId = MotionEventCompat.getPointerId(ev, 0); return false; } return super.onInterceptTouchEvent(ev); } private void onSecondaryPointerUp(MotionEvent ev) { final int pointerIndex = MotionEventCompat.getActionIndex(ev); final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); if (pointerId == mActivePointerId) { final int newPointerIndex = pointerIndex == 0 ? 1 : 0; mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); } }


Ya está registrado en el rastreador de problemas AOSP .

Puede solucionarlo mediante la subclasificación de SwipeRefreshLayout y capturando la excepción, como:

public class SwipeRefreshLayout extends android.support.v4.widget.SwipeRefreshLayout { public SwipeRefreshLayout(Context context) { super(context); } public SwipeRefreshLayout(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onTouchEvent(MotionEvent ev) { try { return super.onTouchEvent(ev); } catch (IllegalArgumentException e) { //Fix for support lib bug, happening when onDestroy() is return true; } } }