Перетаскивание в android 3.x вызывает незаконное появлениеStateException после небольшого числа при перетаскивании

Есть проблема с механизмом перетаскивания в android 3.x: после выполнения некоторых перетаскиваний (скажем, 30 перетаскиваний) возникает нарастание исключения (см. Прикрепленную ссылку)

Https://groups.google.com/forum/#!msg/android-platform/2APvO248NNY/rKI-5dCT8XcJ (я получаю в журнале то же самое, что и к этому сообщению ..)

Техник-андроид отвечает там, что это ошибка в API, и говорит, что единственный способ избежать этой проблемы – вызвать сборщик мусора.

Я сделал это. Исключение больше не было выбрано, но через некоторое время (скажем, более 30-40 перетаскиваний) андроид по какой-то причине перестает вызывать событие drop.

Я попытался «обновить» весь вид, освободив все ресурсы / холсты / чертежи кэша / переработку растровых изображений и заново их создав, и это не помогло (больше не выбрасывало исключение, но все же после некоторого перетаскивания событие drop don ' Т работы)

Единственное, что «помогает» – это закрыть активность и снова перезапустить ее.

Кто-либо решил эту проблему или попробовал бы простую альтернативу ??? (Помимо реализации моей собственной функции перетаскивания).

Я хотел бы получить решение, которое не заставит меня перезапустить или воссоздать все, что не предполагается.

Вот пример кода, который демонстрирует ошибку (не демонстрирует часть, о которой я говорил о проблеме с событием drop после использования 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; } }); } } 

Это 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> 

Это трассировка стека:

 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) 

Чтобы сделать исключение – просто перетащите изображение в какую-то точку на экране и оставьте палец. Повторите это ровно 30 раз, и исключение будет выбрано. Я сделал этот очень простой пример, чтобы продемонстрировать, что исключение было отправлено без каких-либо накладных расходов, вызванных моим приложением.

ТИА

Solutions Collecting From Web of "Перетаскивание в android 3.x вызывает незаконное появлениеStateException после небольшого числа при перетаскивании"

Попробуй это: –

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

Если перезапуск активности помогает, попробуйте перезапустить представление, удалив его и добавив снова (может быть новый экземпляр). Также вы можете попробовать обычный штат (что обычно не помогает), например invalidate (), переопределить onDraw () и посмотреть, почему он вызван или не вызван.

Попробуй это:

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

Это работало для меня на Android 3.2!

Из комментария к вопросу, касающемуся проблемы, которую вы опубликовали в разделе «Группы Google»:

Эта проблема возникает, потому что GC не выполняет сбор перетаскиваний. Но если окно перерисовано, GC выполняет сбор перетаскиваний. Окно будет перерисовываться после открытия мягкой клавиатуры или обновления ImageView или что-то в этом роде.

Похоже, вы можете заставить сборщика мусора собирать объекты перетаскивания, заставляя перерисовывать содержащийся View . У меня нет устройства с поддержкой 3.0, но, возможно, что-то вроде этого стоит попробовать:

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

Возможно, вам понадобится предложенный совет по сборке мусора:

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

Но я думаю, что вы правы, чтобы избежать этого, если это возможно, поэтому я бы попробовал только это, если это не сработает без него.

Кроме того, я думаю, что onTouch() должен возвращать true , так как вы поглотили событие touch.

Прошло много времени с тех пор, как я задал этот вопрос. Когда была выпущена Android-версия Android, эта ошибка уже не существовала. Поэтому, поскольку у Android-андроида нет причин писать приложения, ориентированные на Honeycomb. Во всяком случае, всего 0,3% от всех Android-устройств, работающих под управлением этой версии ОС,

Поэтому для меня ответ – просто не использовать Honeycomb! : ->