onDragEvent()在Nexus上抛出nullpointer

时间:2014-03-26 16:18:49

标签: android android-edittext android-event

如果我犯了任何愚蠢的错误,我很抱歉,但我找不到这个的来源: 我正在尝试在我的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上给了我一个nullpointer。

stackTrace:

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

2 个答案:

答案 0 :(得分:5)

我认为这是EditText小部件和Android中的拖放API的错误。我在其他解决方案中添加了一个链接到问题跟踪器的帖子,但我会在这里重现它以便于阅读。如果你遇到这个问题, please go to the tracker虽然明星这个问题有希望让Android工程师意识到这一点(一厢情愿,我知道)。

崩溃原因

我在尝试使用拖放API在EditText(非常简单的目标)中移动FrameLayout时遇到了4.4.2中的崩溃/错误。我的OnDragListener上只设置了FrameLayout,但显然框架会调用所有孩子View的{​​{1}}回调,如崩溃堆栈跟踪中所示

崩溃发生在内部类OnDragEvent()中,该方法尝试从传递给方法的android.widget.Editor.onDrop()访问ClipData信息。

<强> From 4.4.2 source

DragEvent

在第1830行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 } .... 返回event.getClipData()。然后在第1831行null将触发NPE。这似乎只发生在clipData.getItemCount(),因为他们有一个EditText实例字段,这让我觉得这是一个错误/疏忽。

我找到了两个解决方法。

第一个解决方法:

与注释#1中提出的变通方法类似,您可以在将接收Drag事件的Views层次结构中的android.widget.Editor个对象上设置虚拟OnDragListener。但是,虚拟听众可以简单地

EditText

只需为所有Drag事件返回myEditText.setOnDragListener( new View.OnDragListener() { @Override public boolean onDrag( View v, DragEvent event) { return true; } }); ,无论Action的类型是什么(即通过调用{{{{{{{{{{{{{{{{{{{{ 1}})。这意味着您将拦截Drag事件,并且它不会再被传递给View的实际true回调,因此避免了我们在堆栈跟踪中看到的崩溃。

对于此虚拟侦听器,如果在注释#1中看到event.getAction(),则没有必要具有单独的条件,因为如果您为OnDragEvent()返回false,则您将永远不会收到无论如何(event.getAction() == DragEvent.ACTION_DROP)事件(您可以通过在ACTION_DRAG_STARTED条件中放置日志打印消息来确认这一点,并且您会注意到它永远不会被调用,因为您已在ACTION_DROP中返回ACTION_DROP {1}}条件)。

第二种解决方法:* EDITED(见下文)

由于在尝试访问false中的else null时发生了NPE,因此您可以在开始时向ClipData提供虚拟Editor.onDrop()拖动过程。

这就是我为我的场景所做的:

ClipData

我选择使用辅助方法DragEvent为我创建一个简单的纯文本... <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.newPlainText 1}}参数,因为这也会导致崩溃。

因此,无论您使用ClipData开始拖动过程​​,请务必提供此虚拟ClipData。通过这种解决方法,我不需要虚拟null,我也不会遇到任何NPE崩溃。

注意:如果您使用第一种解决方法,请知道通过从虚拟View.startDrag()返回ClipData,您将有效地阻止DragEvent传播到{{ 1}}所以没有任何代码存在于那里。我不确定这有什么副作用,但它绝对不是一个空洞的方法。

*编辑:在使用OnDragListener小部件进行拖放操作时,我发现true有一些非常奇怪的行为,这是如果你选择第二种解决方法,最终会调用什么。我注意到在使用我建议的虚拟OnDragListener时,&#34; dummyData &#34;如果您尝试将小部件拖动一点同时同时在文本框中移动插入符号,或者键入,则作为第二个参数传递给TextView.onDragEvent()的字符串有时会粘贴/插入EditText进入TextView.onDragEvent(),然后拖动它。

解释起来很困惑,但我能够可靠地重现它。任何读者都可以take a look at the source code获得该方法,如果他们想要尝试并理解它,但我老老实实地厌倦了试图找出Android工程师对此的奇怪意图。由于这种奇怪的行为,我改变了我的第二种解决方法,将空字符串作为第二个参数传递。这似乎缓解了这个问题。

就我个人而言,我最终扩展了ClipData课程并制作了自己的课程,并简单地覆盖了ClipData.newPlainText()EditText而没有打电话给超类(即EditText。这是本质上与第一个解决方法相同,但我还是需要扩展EditText类以添加一些额外的功能。无论onDragEvent()中的原始代码是什么,跳过它都没有&#39这似乎影响了我的个人用例,我没有发现任何我需要的功能缺失。

答案 1 :(得分:0)

NVM,发现了这个问题。 结果可能是框架中的一个错误。

https://code.google.com/p/android/issues/detail?id=21775

报告了与nexus相同的问题。