为什么我按下主屏幕按钮时我的应用程序会崩溃?

3

目前我感到非常沮丧。我已经研究了几天,甚至无法分离出光标问题以外的任何东西。我正在扩展ListActivity,并在OnCreate方法中使用startManagingCursor(newcursor)。以下是代码(数据库已经填充),当按下主页按钮时运行并崩溃:

private void loadAlbums() {
    try {
        newcursor = mDbHelper.getAlbumTitlesCursor();
        dbalbumadapter = new AlbumListCursorAdapter(this, newcursor);
        setListAdapter(dbalbumadapter);
        }
    catch (SQLiteException s) {
        newcursor = null;
        fetchalbums = new FetchAlbumsTask().execute();
        }
    current_view = ALBUMTITLE_VIEW;
}

以下是错误日志:

02-03 13:41:42.379: WARN/dalvikvm(340): threadid=3: thread exiting with uncaught exception (group=0x4001b188)
02-03 13:41:42.389: ERROR/AndroidRuntime(340): Uncaught handler: thread main exiting due to uncaught exception

02-03 13:41:42.590: ERROR/AndroidRuntime(340): java.lang.RuntimeException: Unable to stop activity {com.skip.ngRCv2/com.skip.ngRCv2.ngRC}: java.lang.RuntimeException: Unable to stop activity {com.skip.ngRCv2/com.skip.ngRCv2.MusicLibraryActivity}: java.lang.NullPointerException
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:3227)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at android.app.ActivityThread.handleStopActivity(ActivityThread.java:3272)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at android.app.ActivityThread.access$2500(ActivityThread.java:119)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1880)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at android.os.Handler.dispatchMessage(Handler.java:99)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at android.os.Looper.loop(Looper.java:123)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at android.app.ActivityThread.main(ActivityThread.java:4363)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at java.lang.reflect.Method.invokeNative(Native Method)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at java.lang.reflect.Method.invoke(Method.java:521)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at dalvik.system.NativeStart.main(Native Method) 02-03 13:41:42.590: ERROR/AndroidRuntime(340): 
Caused by: java.lang.RuntimeException: Unable to stop activity {com.skip.ngRCv2/com.skip.ngRCv2.MusicLibraryActivity}: java.lang.NullPointerException
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:3227)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at android.app.ActivityThread.performStopActivity(ActivityThread.java:3174)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at android.app.LocalActivityManager.moveToState(LocalActivityManager.java:176)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at android.app.LocalActivityManager.dispatchStop(LocalActivityManager.java:572)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at android.app.ActivityGroup.onStop(ActivityGroup.java:79)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at android.app.Instrumentation.callActivityOnStop(Instrumentation.java:1169)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at android.app.Activity.performStop(Activity.java:3797)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:3224)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     ... 11 more
02-03 13:41:42.590: ERROR/AndroidRuntime(340): 
Caused by: java.lang.NullPointerException
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at android.app.Activity.performStop(Activity.java:3808)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:3224)
02-03 13:41:42.590: ERROR/AndroidRuntime(340):     ... 18 more

在Activity.performStop(Activity.java:3808)发生了NullPointerException,虽然我无法通过行号交叉验证,但似乎是来自Activity.java中的这个方法:

final void performStop() {
     if (!mStopped) {
         if (mWindow != null) {
             mWindow.closeAllPanels();
         }

         mCalled = false;
         mInstrumentation.callActivityOnStop(this);
         if (!mCalled) {
             throw new SuperNotCalledException(
                 "Activity " + mComponent.toShortString() +
                 " did not call through to super.onStop()");
         }

         synchronized (mManagedCursors) {
             final int N = mManagedCursors.size();
             for (int i=; i<N; i++) {
                 ManagedCursor mc = mManagedCursors.get(i);
                 if (!mc.mReleased) {
                     mc.mCursor.deactivate();
                     mc.mReleased = true;
                 }
             }
         }

         mStopped = true;
     }
     mResumed = false;
 }

我已经尝试在OnStop方法中关闭和停用光标,以及将列表适配器设置为null。我认为当让活动管理光标时,这些操作都是不必要的。我将光标传递给自定义适配器,但我找到的所有示例都没有在适配器内执行任何管理操作。
如果您能帮我缩小引发此异常的范围,我将不胜感激!

听起来你可能让光标由活动管理,但在某个地方你将光标设置为 null,导致了 NPE?! - WarrenFaith
是的,在调用startManagingCursor()时出现了空指针问题。 - dinobud
2个回答

9
如果这是正确的版本,第3808行对应于:
[[我知道这不是官方的Android源代码,但是行号相符]] http://code.google.com/p/pdn-slatedroid/source/browse/trunk/eclair/frameworks/base/core/java/android/app/Activity.java?r=12#3808
mc.mCursor.deactivate();

据我所知,mc 永远不可能为 null。似乎只有在将 null 游标传递到 startManagingCursor() 中时,mCursor(它是 final 类型)才会为 null。我记录了我的笔记以供他人确认。
在将游标传递给 startManagingCursor() 之前,您能否记录一下游标的日志?我很想知道崩溃之前最后一条消息是什么。
当出现 SQL 异常时,您有以下这行代码:
newcursor = null;

我想知道是否涉及到startManagingCursor()的调用。
注:
  • startManagingCursor()创建了一个ManagedCursor

http://code.google.com/p/pdn-slatedroid/source/browse/trunk/eclair/frameworks/base/core/java/android/app/Activity.java?r=12#1549

public void startManagingCursor(Cursor c) {
    synchronized (mManagedCursors) {
        mManagedCursors.add(new ManagedCursor(c));
    }
}
  • ManagedCursor设置final字段mCursor:

http://code.google.com/p/pdn-slatedroid/source/browse/trunk/eclair/frameworks/base/core/java/android/app/Activity.java?r=12#647

private static final class ManagedCursor {
    ManagedCursor(Cursor cursor) {
        mCursor = cursor;
        mReleased = false;
        mUpdated = false;
    }

    private final Cursor mCursor;
    private boolean mReleased;
    private boolean mUpdated;
}
  • 所有对startManagingCursor()的内部调用都受到保护,例如:

http://code.google.com/p/pdn-slatedroid/source/browse/trunk/eclair/frameworks/base/core/java/android/app/Activity.java?r=12#1465

if (c != null) {
    startManagingCursor(c);
}
return c;

哇,这完全帮助我解决了问题。谢谢!也许我很天真(绝对是个新手),但我刚刚想到在设置值之前可以直接调用startManagingCursor(),这意味着它默认为空。这完全解决了我的问题!所以我的问题是,我是否不应该为不同的查询使用相同的游标变量?如果可以,每次更改时我应该调用startManagingCursor()吗? - dinobud
那个和 stopManagingCursor() :) - Oleg Vaskevich

0

在调试器中启动您的应用程序,在NPE上设置异常断点,然后查看它在哪里退出。

这应该会让您了解正在发生什么。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接