Arrastrar y soltar en android 3.x causa illegalStateException después de pequeño número en arrastra

Hay un problema con el mecanismo de arrastrar y soltar en android 3.x: después de hacer algunos arrastres (digamos 30 arrastra) una excepción se acumula (ver el enlace adjunto)

Https://groups.google.com/forum/#!msg/android-platform/2APvO248NNY/rKI-5dCT8XcJ (Estoy recibiendo en el registro lo mismo que adjunto a ese mensaje ..)

El técnico android responde que es un error en la API y dice que la única manera de evitar el problema es llamar a Garbage Collector.

Lo hice. La excepción no se ha lanzado más, pero después de un tiempo (digamos más 30-40 arrastra) android deja de llamar al evento de caída de alguna razón.

Traté de "refrescar" todas las vistas mediante la liberación de todos los recursos / lienzo / dibujo caché / reciclaje de mapas de bits y volver a crearlos y no ayudó (no lanzar la excepción más – pero aún después de algunos arrastra el evento gota ' T trabajo)

Lo único que "ayuda" es cerrar la actividad y reiniciarla de nuevo.

Alguien ha resuelto este problema de alguna manera, o tiene una buena alternativa simple ??? (Además de implementar mi propia función de arrastrar y soltar ..)

Me gustaría obtener una solución que no me obligue a reiniciar o volver a crear cualquier cosa que no suponga ..

Aquí hay código de ejemplo que demuestra el error (no demuestra la parte que dije sobre el problema con el evento drop después de usar System.GC):

public class DragandDropExampleActivity extends Activity { private boolean mIsBeenDragged = false; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final ImageView imageViewToDRag = (ImageView) findViewById(R.id.image_view_to_drag); imageViewToDRag.setClickable(true); imageViewToDRag.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { mIsBeenDragged = true; DragShadowBuilder shadowBuilder = new DragShadowBuilder(imageViewToDRag); imageViewToDRag.startDrag(null, shadowBuilder, imageViewToDRag, 0); } else if (event.getAction() == MotionEvent.ACTION_UP) { mIsBeenDragged = false; } return false; } }); } } 

Este es el xml:

 <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main_frame" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ImageView android:id="@+id/image_view_to_drag" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" > </ImageView> 

Este es el seguimiento de la pila:

 06-04 13:34:32.730: E/View(8061): java.lang.IllegalArgumentException at android.view.Surface.lockCanvasNative(Native Method) at android.view.Surface.lockCanvas(Surface.java:350) at android.view.View.startDrag(View.java:11489) at com.show.dragandrop.DragandDropExampleActivity$1.onTouch(DragandDropExampleActivity.java:32) at android.view.View.dispatchTouchEvent(View.java:4617) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1560) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1291) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1560) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1291) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1560) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1291) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1560) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1291) at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java: 1862) at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1286) at android.app.Activity.dispatchTouchEvent(Activity.java:2315) at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1835) at android.view.View.dispatchPointerEvent(View.java:4689) at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2415) at android.view.ViewRoot.handleMessage(ViewRoot.java:2077) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:132) at android.app.ActivityThread.main(ActivityThread.java:4126) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:491) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602) at dalvik.system.NativeStart.main(Native Method) 

Para hacer que la excepción se acumule – simplemente arrastre la imagen a algún punto en la pantalla, y deje el dedo. Repetir exactamente 30 veces, y la excepción se lanza. Hice este ejemplo muy simple, para demostrar que la excepción lanzada sin ninguna sobrecarga causada por mi aplicación.

TIA

Prueba esto: –

 private OnTouchListener drag = new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_MOVE) { setViewPosition(v, Math.round(event.getRawX()), Math.round(event.getRawY())); } return false; } }; private void setViewPosition(View v, int x, int y) { if (v != null) { LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); params.leftMargin = (x - v.getMeasuredWidth() / 2); params.topMargin = (y - v.getMeasuredHeight() / 2); v.setLayoutParams(params); v.invalidate(); } } 

Si se está reiniciando la actividad, entonces intente reiniciar la vista, eliminándola y agregándola de nuevo (puede ser una nueva instancia). También puede probar el personal regular (que por lo general no ayuda) como invalidate (), anular el onDraw () y ver por qué se llama o no se llama.

Prueba esto:

 imageViewToDRag.startDrag(null, shadowBuilder, imageViewToDRag, 0); System.gc(); 

Funcionó para mí en Android 3.2!

De un comentario sobre la pregunta que cubre el problema que publicó en la discusión de Google Groups sobre:

Este problema se produce porque GC no realiza la recopilación de arrastra. Pero si la ventana se redibuja, GC realiza la recolección de arrastres. La ventana se volverá a dibujar después de que el teclado virtual se haya abierto o de que algunos ImageView hayan sido actualizados o algo así.

Por lo que suena como usted puede obtener el recolector de basura para recopilar los objetos de arrastrar forzando un redibujo de la View contiene. No tengo un dispositivo 3.0 a mano, pero quizás algo como esto valdría la pena intentarlo:

  } else if (event.getAction() == MotionEvent.ACTION_UP) { findViewById(R.id.main_frame).invalidate(); } 

Es posible que necesite la sugerencia de recogida de basura sugerida en allí también:

  } else if (event.getAction() == MotionEvent.ACTION_UP) { findViewById(R.id.main_frame).invalidate(); System.gc(); } 

Pero creo que tienes razón al querer evitar que si es posible, así que sólo lo intentaría si no funciona sin él.

Además, creo que onTouch() debería devolver true , ya que has consumido el evento táctil.

Pasó mucho tiempo desde que hice esa pregunta. Cuando se lanzó Android ICS – este error ya no existía. Así que desde android ICS no hay realmente ninguna razón para escribir aplicaciones dirigidas a Honeycomb. De todos modos sólo el 0,3% del total de dispositivos Android que ejecutan esta versión del sistema operativo,

Así que para mí la respuesta es – ¡no usar Honeycomb! : ->

  • Obtener enlace de clic de evento en una vista web Android
  • Manejo de la rotación de la pantalla en WebView
  • Cómo actualizar la vista de la vista de fila de elementos anteriores de la vista de reciclaje
  • Establecer diferentes indicadores para diferentes grupos en android
  • Incluyendo las actividades de Android (y sus diseños) en archivos JAR
  • ¿Cómo abrir o expandir la barra de estado a través de la intención?
  • ANR en SurfaceView en dispositivos específicos solamente - La única solución es un tiempo de sueño corto
  • ¿Rellenar ListFragments con una vista personalizada?
  • El fondo de la vista ampliable se vuelve negro cuando se amplía
  • ExpandableListView OnGroupCollapseListener - cualquier oyente / observador para ANTES que ocurra el colapso?
  • agregar vista (vista de texto) en AsyncTask
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.