Android onDragEvent()在Nexus上抛出空指针

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

如果我犯了愚蠢的错误,我很抱歉,但我找不到这一错误的根源: 我正在尝试在我的EditText“etItem”上实现onDrag侦听器 这是我的代码:

 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);
...