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! : ->

  • Cómo extender la etiqueta de inclusión en Android
  • Cambios en una página web a través de JavaScript que no aparecen en WebView. ¿Hay una manera de forzar el WebView para volver a dibujar su contenido?
  • Cómo convertir linearlayout a imagen
  • Contraer un grupo de forma programática en ExpandableListView
  • Vista de visualización en la parte superior de la barra de acción
  • ¿Diversas vistas para el artículo del hilandero y del hilandero?
  • Animación de una vista mientras que ListView no está funcionando
  • Textview dentro de RelativeLayout en la vista personalizada ¿No se aplica la gravedad correctamente?
  • Creación de un libro que almacena la vista de cuadrícula en android
  • Vista web de Android en la mitad de la pantalla
  • Cómo obtener elementos de los niños de forma dinámica dentro de expandiblelistview haciendo clic en el nodo padre en android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.