从onCreateLoader返回的对象不能是非静态内部成员类:DumbLoader。

4

我正在尝试在我的安卓项目中使用Cursor LoaderCustom Cursor Adapter与数据库(Sqlite本地数据库)进行交互。我希望通过使用Cursor Loader和Adapter异步地从本地数据库中获取数据并向我的listview中填充数据。下面是我的类、子类和方法:

        // Home Activity class
        public class HomeActivity extends FragmentActivity implements LoaderCallbacks<Cursor> {
                DotCursorAdapter mAdapter;
                private ListView lv;
                private  final int LOADER_ID = 1932;

         DatabaseHandler dbHelper = new DatabaseHandler(this);

         @Override
         protected void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
                setContentView(R.layout.home_activity);
             lv = (ListView) findViewById(R.id.lists);


             mAdapter = new DotCursorAdapter(this, null,0);
             lv.setAdapter(mAdapter);

             getSupportLoaderManager().initLoader(LOADER_ID, null, this);   
        }





         @Override
         public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
             return new DumbLoader(this);
         }
         @Override
         public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
             mAdapter.swapCursor(cursor);
         }
         @Override
         public void onLoaderReset(Loader<Cursor> cursorLoader) {
             mAdapter.swapCursor(null);
         }



        /**
         * DumbLoader sub class 
         */ 
         public class DumbLoader extends CursorLoader {
             private static final String TAG = "DumbLoader";
             public DumbLoader(Context context) {
                 super(context);
             }
             @Override
             public Cursor loadInBackground() {
                 Cursor c = dbHelper.fetchAllCountries();

                 return c;

             }
        }






        /**
         * DotCursor Adapter sub class
         */
        public final class DotCursorAdapter extends CursorAdapter {

             public DotCursorAdapter(Context context, Cursor cursor, int flags) {
                  super(context, cursor, 0);
              }



             @Override
             public void bindView(View view, Context context, Cursor cursor) {

                  // Find fields to populate in inflated template
                  TextView tvBody = (TextView) view.findViewById(R.id.header_text);

                  String body = cursor.getString(cursor.getColumnIndexOrThrow("fname"));
                  // Populate fields with extracted properties
                  tvBody.setText(body);


             }
             @Override
              public View newView(Context context, Cursor cursor, ViewGroup parent) {
                  return LayoutInflater.from(context).inflate(R.layout.list_cardview_activity, parent, false);
              }
            }
    }

以下是我的数据库处理程序方法,它从数据库中获取数据。
public  Cursor fetchAllCountries() {
    SQLiteDatabase db = this.getReadableDatabase();

      Cursor mCursor = db.query(TABLE_LOGIN, new String[] {KEY_ID,KEY_FIRSTNAME},
        null, null, null, null, null);

      if (mCursor != null) {
       mCursor.moveToFirst();
      }
      return mCursor;
     }

问题描述

执行以上代码后,从日志中可以看到出现错误消息并且应用程序崩溃。

主要错误信息如下:

从onCreateLoader返回的对象不应该是非静态内部成员类。

以下是我的日志详细信息:

09-21 16:13:25.563: D/AbsListView(26541): 获取MotionRecognitionManager 09-21 16:13:25.568: D/AndroidRuntime(26541): 关闭 VM 09-21 16:13:25.573: W/dalvikvm(26541): 线程 ID=1: 线程退出,带有未捕获的异常 (group=0x411372a0) 09-21 16:13:25.573: E/AndroidRuntime(26541): 致命错误:主线程 09-21 16:13:25.573: E/AndroidRuntime(26541): java.lang.RuntimeException: 无法启动活动 ComponentInfo{com.alliswell.alliswell/com.alliswell.alliswell.HomeActivity}:java.lang.IllegalArgumentException:从 onCreateLoader 返回的对象不能是非静态内部成员类:DumbLoader{418dc668 id=0} 09-21 16:13:25.573: E/AndroidRuntime(26541): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2110) 09-21 16:13:25.573: E/AndroidRuntime(26541): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2135) 09-21 16:13:25.573: E/AndroidRuntime(26541): at android.app.ActivityThread.access$700(ActivityThread.java:140) 09-21 16:13:25.573: E/AndroidRuntime(26541): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1237) 09-21 16:13:25.573: E/AndroidRuntime(26541): at android.os.Handler.dispatchMessage(Handler.java:99) 09-21 16:13:25.573: E/AndroidRuntime(26541): at android.os.Looper.loop(Looper.java:137) 09-21 16:13:25.573: E/AndroidRuntime(26541): at android.app.ActivityThread.main(ActivityThread.java:4921) 09-21 16:13:25.573: E/AndroidRuntime(26541): at java.lang.reflect.Method.invokeNative(Native Method) 09-21 16:13:25.573: E/AndroidRuntime(26541): at java.lang.reflect.Method.invoke(Method.java:511) 09-21 16:13:25.573: E/AndroidRuntime(26541): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038) 09-21 16:13:25.573: E/AndroidRuntime(26541): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805) 09-21 16:13:25.573: E/AndroidRuntime(26541): at dalvik.system.NativeStart.main(Native Method) 09-21 16:13:25.573: E/AndroidRuntime(26541): Caused by: java.lang.IllegalArgumentException:从 onCreateLoader 返回的对象不能是非静态内部成员类:DumbLoader{418dc668 id=0} 09-21 16:13:25.573: E/AndroidRuntime(26541): at android.support.v4.app.LoaderManagerImpl$LoaderInfo.start(LoaderManager.java:257) 09-21 16:13:25.573: E/AndroidRuntime(26541): at android.support.v4.app.LoaderManagerImpl.doStart(LoaderManager.java:714) 09-21 16:13:25.573: E/AndroidRuntime(26541): at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:556) 09-21 16:13:25.573: E/AndroidRuntime(26541): at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1178) 09-21 16:13:25.573: E/AndroidRuntime(26541): at android.app.Activity.performStart(Activity.java:5198) 09-21 16:13:25.573: E/AndroidRuntime(26541): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2083) 09-21 16:13:25.573: E/AndroidRuntime(26541): …11 more

我认为我的代码存在问题,如果有人能帮助我解决这个问题,我将不胜感激。谢谢。


4
错误非常明显:将DumbLoader类移出HomeActivity类或将其声明为静态。 - user
公共的静态类DumbLoader扩展自CursorLoader {...} - Eugen Pechanec
2个回答

7
你有两种方法可以解决这个问题:
1.- 创建DumbLoader.java文件并将其设置为以下内容:
public class DumbLoader extends CursorLoader {

     private DatabaseHandler mDBHelper;

     public DumbLoader(Context context, DatabaseHandler dbHelper) {
         super(context);
         mDBHelper = dbHelper;
     }

     @Override
     public Cursor loadInBackground() {
         return mDBHelper.fetchAllCountries();
     }
}

2.- 使用static修饰符对你的Activity的DumbLoader嵌套类进行修饰,使其如下所示:

public class HomeActivity extends FragmentActivity implements LoaderCallbacks<Cursor> {

    //onCreate(), etc...

    //Make DumbLoader nested class STATIC
    public static class DumbLoader extends CursorLoader {

        private DatabaseHandler mDBHelper;

        public DumbLoader(Context context, DatabaseHandler dbHelper) {
            super(context);
            mDBHelper = dbHelper;
        }

        @Override
        public Cursor loadInBackground() {
            return mDBHelper.fetchAllCountries();
        }
}

这段代码无法编译,将dbHelper传入构造函数即可解决。 - Eugen Pechanec
@EugenPechanec 这是真的,我会修复它。 - BamsBamx

0

LuksProgBamsBamx 的建议是正确的。简单来说,如果您使用一个非静态内部类扩展AsyncTaskAsyncTaskLoader,或者如果在该类中发生了任何不在主线程上的活动,则会抛出运行时异常。原因是,如果某个后台任务正在非静态内部类中进行,同时父活动被销毁,则内部类始终存储有其父类的上下文,这将导致内存泄漏。为了防止内存泄漏,必须在静态内部类或单独的个体类中执行任何后台操作。更多见解请参见此 SO 线程


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