android 3.x中的拖放导致拖动后的小数字后面的illegalStateException

在Android 3.x上有拖放机制的问题:在做了一些拖动(比如30次拖动)之后会产生exception(参见附件链接)

https://groups.google.com/forum/#!msg/android-platform/2APvO248NNY/rKI-5dCT8XcJ (我在日志中收到与该post相同的内容..)

android技术人员在那里回答它是API中的错误,并说避免问题的唯一方法是调用垃圾收集器。

我做的。 exception没有被抛出,但过了一段时间(比如更多30-40次拖动)android停止从某种原因调用drop事件。

我试图通过释放所有资源/canvas/绘图缓存/回收位图来“刷新”所有视图并重新创建它们并且它没有帮助(不再抛出exception – 但仍然有一些拖拽掉落事件’工作)

“帮助”唯一的事情是关闭活动并重新启动它。

有人以某种方式解决了这个问题,或者有一个简单的替代方案??? (旁边实现我自己的拖放function..)

我想得到解决方案,不会强迫我重新启动或重新创建任何不想要的东西..

这里是演示错误的示例代码 (没有演示我在使用System.GC后对drop事件的问题所说的部分):

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:

     

这是堆栈跟踪:

 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) 

使exception累积 – 只需将图像拖动到屏幕上的某个点,然后离开手指即可。 正好重复30次,抛出exception。 我做了这个非常简单的例子,以certificate抛出的exception没有任何由我的应用程序引起的开销。

TIA

尝试这个: –

 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 ,因为你已经消耗了触摸事件。

自从我提出这个问题以来,已经过了很多时间。 当android ICS发布时 – 这个bug不再存在了。 所以自从android ICS以来,没有理由编写针对Honeycomb的应用程序。 无论如何,只有0.3%的Android设备运行此版本的操作系统,

所以对我来说答案是 – 不要使用Honeycomb! – >