Android onDragEvent()在Nexus上抛出空指针
如果我犯了愚蠢的错误,我很抱歉,但我找不到这一错误的根源: 我正在尝试在我的EditText“etItem”上实现onDrag侦听器 这是我的代码:Android onDragEvent()在Nexus上抛出空指针,android,android-edittext,android-event,Android,Android Edittext,Android Event,如果我犯了愚蠢的错误,我很抱歉,但我找不到这一错误的根源: 我正在尝试在我的EditText“etItem”上实现onDrag侦听器 这是我的代码: etItem.setOnDragListener(new OnDragListener(){ @Override public boolean onDrag(View v, DragEvent dragevent) { if(null!=dragevent &am
etItem.setOnDragListener(new OnDragListener(){
@Override
public boolean onDrag(View v, DragEvent dragevent) {
if(null!=dragevent && null!=v){
if( dragevent.getAction() == DragEvent.ACTION_DROP )
{
View view = (View) dragevent.getLocalState();
ViewGroup owner = (ViewGroup) view.getParent();
int itemNum = (Integer) view.getTag();
itemAmounts[itemNum] = 0;
owner.removeView(view);
return true;
}
}
return false;
}});
这在我的Samsng Galaxy Grand上运行良好,但在Nexus上给了我一个空指针
堆栈跟踪:
03-26 15:47:21.185: E/AndroidRuntime(1439): FATAL EXCEPTION: main
03-26 15:47:21.185: E/AndroidRuntime(1439): java.lang.NullPointerException
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.widget.Editor.onDrop(Editor.java:1797)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.widget.TextView.onDragEvent(TextView.java:8350)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.View.dispatchDragEvent(View.java:16375)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1237)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1237)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1237)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1237)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1237)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1237)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1237)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1237)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1237)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewRootImpl.handleDragEvent(ViewRootImpl.java:3838)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewRootImpl.access$600(ViewRootImpl.java:95)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:2999)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.os.Handler.dispatchMessage(Handler.java:99)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.os.Looper.loop(Looper.java:137)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.app.ActivityThread.main(ActivityThread.java:5041)
03-26 15:47:21.185: E/AndroidRuntime(1439): at java.lang.reflect.Method.invokeNative(Native Method)
03-26 15:47:21.185: E/AndroidRuntime(1439): at java.lang.reflect.Method.invoke(Method.java:511)
03-26 15:47:21.185: E/AndroidRuntime(1439): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
03-26 15:47:21.185: E/AndroidRuntime(1439): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
03-26 15:47:21.185: E/AndroidRuntime(1439): at dalvik.system.NativeStart.main(Native Method)
03-26 15:47:21.345: W/ActivityManager(297): Force finishing activity com.listcalc.main/.MainActivityFree
NVM,发现了问题。
结果可能是框架中的一个bug
报告了nexus的相同问题。我认为这是Android中的EditText小部件和拖放API的错误。我在另一个解决方案中链接的问题跟踪程序中添加了一个帖子,但为了便于阅读,我将在这里复制它。如果你遇到了这个问题,尽管和star希望能让安卓工程师意识到这个问题(我知道是一厢情愿) 撞车原因 在4.4.2中,我在尝试使用拖放API在
FrameLayout
中移动EditText
时遇到了这个崩溃/错误(非常简单的目标)。在我的FrameLayout
上只设置了一个OnDragListener
,但显然框架调用了所有子视图的OnDragEvent()
回调,如崩溃堆栈跟踪中所示
崩溃发生在内部类android.widget.Editor.onDrop()
中,该方法尝试从传递给该方法的DragEvent
中访问ClipData
信息
:
1828 void onDrop(DragEvent event) {
1829 StringBuilder content = new StringBuilder("");
1830 ClipData clipData = event.getClipData();
1831 final int itemCount = clipData.getItemCount();
1832 for (int i=0; i < itemCount; i++) {
1833 Item item = clipData.getItemAt(i);
1834 content.append(item.coerceToStyledText(mTextView.getContext()));
1835 }
....
只要为所有拖动事件返回true
,您就可以告诉框架您已经处理了事件,而不管操作类型是什么(即调用event.getAction()
)。这意味着您将截获拖动事件,它将不再传递给视图的实际OnDragEvent()
回调,因此避免了我们在stacktrace中看到的崩溃
对于此虚拟侦听器,没有必要为(event.getAction()==DragEvent.ACTION\u DROP)
设置单独的条件,如注释1中所示,因为如果为ACTION\u DRAG\u start
返回false,您无论如何都不会收到ACTION\u DROP
事件(您可以通过在ACTION\u DROP
条件中放置日志打印消息来确认这一点,您会注意到它从未被调用,因为您已经在else
条件中返回了false
)
第二种解决方法:*已编辑(见下文)
由于NPE是在尝试访问Editor.onDrop()
中的null
ClipData
时发生的,因此在开始拖动过程时,只需向DragEvent
提供一个虚拟的ClipData
这就是我在我的场景中所做的:
... <other code>
ClipData dummyData = ClipData.newPlainText("dummyData", ""); // don't forget to pass empty String
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v);
v.startDrag(dummyData, shadowBuilder, v, 0);
...
。。。
ClipData dummyData=ClipData.newPlainText(“dummyData”,“”);//不要忘记传递空字符串
DragShadowBuilder shadowBuilder=新视图。DragShadowBuilder(v);
v、 startDrag(dummyData,shadowBuilder,v,0);
...
我选择使用helper方法ClipData.newPlainText
为我创建一个简单的纯文本ClipData
,因为你不能仅仅用它的构造函数和null
参数构造一个ClipData
,因为这也会导致崩溃
因此,无论在何处,您都可以使用View.startDrag()
开始拖动过程。请确保提供此虚拟ClipData
。通过此解决方案,我不需要虚拟OnDragListener
,也不会发生任何NPE崩溃
注意:如果使用第一种解决方法,请知道通过从虚拟OnDragListener
返回true
,将有效阻止DrageEvent传播到TextView.onDragEvent()
因此,其中的所有代码都不会被调用。我不确定这种方法是否会产生副作用,但它肯定不是一种空方法
*编辑:在使用EditText
小部件进行拖放操作之后,我发现TextView.onDragEvent()存在一些非常奇怪的行为
如果使用第二种解决方法,最终会调用它。我注意到,当使用我建议的伪ClipData
时,作为第二个参数传递给ClipData.newPlainText()的“dummyData”字符串
有时会被粘贴/插入到EditText
中,如果您尝试在文本框中移动插入符号的同时拖动小部件,或者在EditText
中键入,然后再拖动它
解释起来非常混乱,但我能够可靠地复制它。任何读者如果想尝试并理解它,都可以使用该方法,但我真的厌倦了试图找出Android工程师对此的奇怪意图。由于这种奇怪的行为,我改变了第二种变通方法,将空字符串作为seco传递这似乎缓解了问题
就我个人而言,我最终扩展了EditText
类,创建了自己的类,并简单地将onDragEvent()
重写为return true;
,而没有调用超类(即TextView.onDragEvent())
。这本质上与第一种解决方法相同,但我还是需要扩展EditText
类来添加一些额外的功能。无论TextView.onDragEvent()中的原始代码是什么
是的,跳过它似乎不会影响我的个人用例,我也没有注意到我需要的任何功能的缺失
... <other code>
ClipData dummyData = ClipData.newPlainText("dummyData", ""); // don't forget to pass empty String
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v);
v.startDrag(dummyData, shadowBuilder, v, 0);
...