0

我确实有一个问题让我很头疼。我通过自定义内容提供程序在sqlite数据库中存储我的城市的一些图像。但是,当我运行我的应用程序时,我得到一个空游标。尝试调用空对象引用的接口方法'int android.database.Cursor.getCount()'

Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'int android.database.Cursor.getCount()' on a null object reference 
               at theo.testing.androidcustomloaders.fragments.MainActivityFragment.onActivityCreated(MainActivityFragment.java:74) 
               at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:2089) 
               at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1133) 
               at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1290) 
               at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:801) 
               at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1677) 
               at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:388) 
               at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:604) 
               at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:178) 
               at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1220) 
               at android.app.Activity.performStart(Activity.java:5992) 
               at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2261) 
               at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2358)  
               at android.app.ActivityThread.access$800(ActivityThread.java:144)  
               at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)  
               at android.os.Handler.dispatchMessage(Handler.java:102)  
               at android.os.Looper.loop(Looper.java:135)  
               at android.app.ActivityThread.main(ActivityThread.java:5219)  
               at java.lang.reflect.Method.invoke(Native Method)  
               at java.lang.reflect.Method.invoke(Method.java:372)  
               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898)  
               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)  

这将意味着信息没有正确存储,或者我的提供者的Uri在某种程度上是有缺陷的。所以。

MyCityContract

public class MyCityContract { 

public static final String CONTENT_AUTHORITY = "theo.testing.customloaders"; 

public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY); 

public static final class MyCityEntry implements BaseColumns{ 
    //table name 
    public static final String TABLE_MY_CITY = "my_city"; 
    //columns 
    public static final String _ID = "_id"; 
    public static final String COLUMN_NAME = "name"; 
    public static final String COLUMN_ICON = "icon"; 

    // create content uri 
    public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon() 
      .appendPath(TABLE_MY_CITY).build(); 
    // create cursor of base type directory for multiple entries 
    public static final String CONTENT_DIR_TYPE = 
      ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + TABLE_MY_CITY; 
    // create cursor of base type item for single entry 
    public static final String CONTENT_ITEM_TYPE = 
      ContentResolver.CURSOR_ITEM_BASE_TYPE +"/" + CONTENT_AUTHORITY + "/" + TABLE_MY_CITY; 

    // for building URIs on insertion 
    public static Uri buildFlavorsUri(long id){ 
     return ContentUris.withAppendedId(CONTENT_URI, id); 
    } 

    } 
} 

MyCityDbHelper

public class MyCityDbHelper extends SQLiteOpenHelper{ 
public static final String LOG_TAG = MyCityDbHelper.class.getSimpleName(); 
//name & version 
public static final String DATABASE_NAME = "city.db"; 
public static final int DATABASE_VERSION = 4; 
// Create the database 
public MyCityDbHelper(Context context) { 
    super(context, DATABASE_NAME,null,DATABASE_VERSION); 
} 

@Override 
public void onCreate(SQLiteDatabase sqLiteDatabase) { 
    final String SQL_CREATE_MY_CITY_TABLE = "CREATE TABLE " + 
      MyCityContract.MyCityEntry.TABLE_MY_CITY + "(" + MyCityContract.MyCityEntry._ID + 
      " INTEGER PRIMARY KEY AUTOINCREMENT, " + 
      MyCityContract.MyCityEntry.COLUMN_NAME + " TEXT NOT NULL, " + 
      MyCityContract.MyCityEntry.COLUMN_ICON + " INTEGER NOT NULL);"; 


    sqLiteDatabase.execSQL(SQL_CREATE_MY_CITY_TABLE); 
} 

@Override 
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) { 
    Log.w(LOG_TAG, "Upgrading database from version " + oldVersion + " to " + 
      newVersion + ". OLD DATA WILL BE DESTROYED"); 
    // Drop the table 
    sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + MyCityContract.MyCityEntry.TABLE_MY_CITY); 
    sqLiteDatabase.execSQL("DELETE FROM SQLITE_SEQUENCE WHERE NAME = '" + 
      MyCityContract.MyCityEntry.TABLE_MY_CITY + "'"); 

    // re-create database 
    onCreate(sqLiteDatabase); 
    } 
} 

MyCityProvider

public class MyCityProvider extends ContentProvider { 
private static final String LOG_TAG = MyCityProvider.class.getSimpleName(); 
private static final UriMatcher sUriMatcher = buildUriMatcher(); 
private MyCityDbHelper myCityDbHelper; 

//Codes for UriMatcher 
private static final int MY_CITY = 100; 
private static final int MY_CITY_WITH_ID = 200; 


private static UriMatcher buildUriMatcher(){ 
    // Build a UriMatcher by adding a specific code to return based on a match 
    // It's common to use NO_MATCH as the code for this case. 
    final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); 
    final String authority = MyCityContract.CONTENT_AUTHORITY; 

    //add code for each URI 


matcher.addURI(authority,MyCityContract.MyCityEntry.TABLE_MY_CITY,MY_CITY); 
    matcher.addURI(authority,MyCityContract.MyCityEntry.TABLE_MY_CITY + "/#",MY_CITY_WITH_ID); 

    return matcher; 

} 
@Override 
public boolean onCreate() { 
    myCityDbHelper = new MyCityDbHelper(getContext()); 

    return true; 
} 

@Override 
public String getType(Uri uri) { 
    final int match = sUriMatcher.match(uri); 

    switch (match){ 
     case MY_CITY: { 
      return MyCityContract.MyCityEntry.CONTENT_DIR_TYPE; 
     } 
     case MY_CITY_WITH_ID:{ 
      return MyCityContract.MyCityEntry.CONTENT_ITEM_TYPE; 

     } 
     default:{ 
      throw new UnsupportedOperationException("Unknown uri: " + uri); 
     } 
    } 
} 
@Override 
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder){ 
    Cursor retCursor; 
    switch(sUriMatcher.match(uri)){ 
     // All Flavors selected 
     case MY_CITY:{ 
      retCursor = myCityDbHelper.getReadableDatabase().query(
        MyCityContract.MyCityEntry.TABLE_MY_CITY, 
        projection, 
        selection, 
        selectionArgs, 
        null, 
        null, 
        sortOrder); 
      return retCursor; 
     } 
     // Individual flavor based on Id selected 
     case MY_CITY_WITH_ID:{ 
      retCursor = myCityDbHelper.getReadableDatabase().query(
        MyCityContract.MyCityEntry.TABLE_MY_CITY, 
        projection, 
        MyCityContract.MyCityEntry._ID + " = ?", 
        new String[] {String.valueOf(ContentUris.parseId(uri))}, 
        null, 
        null, 
        sortOrder); 
      return retCursor; 
     } 
     default:{ 
      // By default, we assume a bad URI 
      throw new UnsupportedOperationException("Unknown uri: " + uri); 
     } 
    } 
} 




@Override 
public Uri insert(Uri uri, ContentValues contentValues) { 
    final SQLiteDatabase db = myCityDbHelper.getWritableDatabase(); 

    Uri returnUri; 

    switch (sUriMatcher.match(uri)){ 
     case MY_CITY: 

      long _id = db.insert(MyCityContract.MyCityEntry.TABLE_MY_CITY,null,contentValues); 
      Log.d("id",String.valueOf(_id)); 
      // insert unless it is already contained in the database 
      if(_id>0){ 
       returnUri = MyCityContract.MyCityEntry.buildFlavorsUri(_id); 
      }else { 
       throw new android.database.SQLException("Failed to insert row into: " + uri); 
      } 
      break; 
     default: { 
      throw new UnsupportedOperationException("Unknown uri: " + uri); 
     } 
    } 

    getContext().getContentResolver().notifyChange(uri,null); 
    return returnUri; 
} 

@Override 
public int delete(Uri uri, String selection, String[] selectionArgs) { 
    final SQLiteDatabase db = myCityDbHelper.getWritableDatabase(); 
    final int match = sUriMatcher.match(uri); 
    int numDeleted; 
    switch(match){ 
     case MY_CITY: 
      numDeleted = db.delete(
        MyCityContract.MyCityEntry.TABLE_MY_CITY, selection, selectionArgs); 
      // reset _ID 
      db.execSQL("DELETE FROM SQLITE_SEQUENCE WHERE NAME = '" + 
        MyCityContract.MyCityEntry.TABLE_MY_CITY + "'"); 
      break; 
     case MY_CITY_WITH_ID: 
      numDeleted = db.delete(MyCityContract.MyCityEntry.TABLE_MY_CITY, 
        MyCityContract.MyCityEntry._ID + " = ?", 
        new String[]{String.valueOf(ContentUris.parseId(uri))}); 
      // reset _ID 
      db.execSQL("DELETE FROM SQLITE_SEQUENCE WHERE NAME = '" + 
        MyCityContract.MyCityEntry.TABLE_MY_CITY + "'"); 

      break; 
     default: 
      throw new UnsupportedOperationException("Unknown uri: " + uri); 
    } 

    return numDeleted; 
} 
@Override 
public int bulkInsert(Uri uri, ContentValues[] values){ 
    final SQLiteDatabase db = myCityDbHelper.getWritableDatabase(); 
    final int match = sUriMatcher.match(uri); 
    switch(match){ 
     case MY_CITY: 
      // allows for multiple transactions 
      db.beginTransaction(); 

      // keep track of successful inserts 
      int numInserted = 0; 
      try{ 
       for(ContentValues value : values){ 
        if (value == null){ 
         throw new IllegalArgumentException("Cannot have null content values"); 
        } 
        long _id = -1; 
        try{ 
         _id = db.insertOrThrow(MyCityContract.MyCityEntry.TABLE_MY_CITY, 
           null, value); 
        }catch(SQLiteConstraintException e) { 
         Log.w(LOG_TAG, "Attempting to insert " + 
           value.getAsString(
             MyCityContract.MyCityEntry.COLUMN_NAME) 
           + " but value is already in database."); 
        } 
        if (_id != -1){ 
         numInserted++; 
        } 
       } 
       if(numInserted > 0){ 
        // If no errors, declare a successful transaction. 
        // database will not populate if this is not called 
        db.setTransactionSuccessful(); 
       } 
      } finally { 
       // all transactions occur at once 
       db.endTransaction(); 
      } 
      if (numInserted > 0){ 
       // if there was successful insertion, notify the content resolver that there 
       // was a change 
       getContext().getContentResolver().notifyChange(uri, null); 
      } 
      return numInserted; 
     default: 
      return super.bulkInsert(uri, values); 
    } 
} 
@Override 
public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs){ 
    final SQLiteDatabase db = myCityDbHelper.getWritableDatabase(); 
    int numUpdated = 0; 

    if (contentValues == null){ 
     throw new IllegalArgumentException("Cannot have null content values"); 
    } 

    switch(sUriMatcher.match(uri)){ 
     case MY_CITY:{ 
      numUpdated = db.update(MyCityContract.MyCityEntry.TABLE_MY_CITY, 
        contentValues, 
        selection, 
        selectionArgs); 
      break; 
     } 
     case MY_CITY_WITH_ID: { 
      numUpdated = db.update(MyCityContract.MyCityEntry.TABLE_MY_CITY, 
        contentValues, 
        MyCityContract.MyCityEntry._ID + " = ?", 
        new String[] {String.valueOf(ContentUris.parseId(uri))}); 
      break; 
     } 
     default:{ 
      throw new UnsupportedOperationException("Unknown uri: " + uri); 
     } 
    } 

    if (numUpdated > 0){ 
     getContext().getContentResolver().notifyChange(uri, null); 
    } 

    return numUpdated; 
    } 
} 

MainActivityFragment

public class MainActivityFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>{ 
private static final String LOG_TAG = MainActivityFragment.class.getSimpleName(); 
private MyCityAdpapter myCityAdpapter; 
private static final int CURSOR_LOADER_ID = 0; 
private GridView mGridView; 


MyCity[] mMyCity = { 
     new MyCity("Ancient Theatre - Larisa", R.drawable.larissa1), 

     new MyCity("Ancient Theatre - Larisa", R.drawable.larissa2), 
     new MyCity("Municipality park", R.drawable.larissa3), 
     new MyCity("Municipality park", R.drawable.larissa4), 
     new MyCity("Old trains",R.drawable.larissa5), 
     new MyCity("Old trains",R.drawable.larissa6), 
     new MyCity("Church", 
       R.drawable.larissa7), 
     new MyCity("Church", 
       R.drawable.larissa8), 
     new MyCity("Alcazar park", 
       R.drawable.larissa9), 
     new MyCity("Alcazar park", 
       R.drawable.larissa10), 
     new MyCity("AEL FC Arena", 
       R.drawable.larissa11), 
     new MyCity("AEL FC Arena", 
       R.drawable.larissa12), 
     new MyCity("Larissa Fair", 
       R.drawable.larissa13), 
     new MyCity("Larissa Fair", 
       R.drawable.larissa14), 
     new MyCity("Larissa Fair", 
       R.drawable.larissa15), 
     new MyCity("Larissa Fair", 
       R.drawable.larissa16) 

}; 
public MainActivityFragment() { 
    // Required empty public constructor 
} 

@Override 
public void onActivityCreated(@Nullable Bundle savedInstanceState) { 
    Cursor c = 
      getActivity().getContentResolver().query(MyCityContract.MyCityEntry.CONTENT_URI, 
        new String[]{MyCityContract.MyCityEntry._ID}, 
        null, 
        null, 
        null); 
    if (c.getCount() == 0){ 
     insertData(); 
    } 
    // initialize loader 
    getLoaderManager().initLoader(CURSOR_LOADER_ID, null, this); 
    super.onActivityCreated(savedInstanceState); 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 
    // Inflate the layout for this fragment 
    // inflate fragment_main layout 
    final View rootView = inflater.inflate(R.layout.fragment_main_activity, container, false); 


    // initialize our FlavorAdapter 
    myCityAdpapter = new MyCityAdpapter(getActivity(), null, 0, CURSOR_LOADER_ID); 
    // initialize mGridView to the GridView in fragment_main.xml 
    mGridView = (GridView) rootView.findViewById(R.id.flavors_grid); 
    // set mGridView adapter to our CursorAdapter 
    mGridView.setAdapter(myCityAdpapter); 

    return rootView; 

} 

// insert data into database 
public void insertData(){ 
    ContentValues[] cityValuesArr = new ContentValues[mMyCity.length]; 
    // Loop through static array of MyCity, add each to an instance of ContentValues 
    // in the array of ContentValues 
    for(int i = 0; i < mMyCity.length; i++){ 
     cityValuesArr[i] = new ContentValues(); 
     cityValuesArr[i].put(MyCityContract.MyCityEntry.COLUMN_ICON, mMyCity[i].image); 
     cityValuesArr[i].put(MyCityContract.MyCityEntry.COLUMN_NAME, 
       mMyCity[i].name); 

    } 

    // bulkInsert our ContentValues array 
    getActivity().getContentResolver().bulkInsert(MyCityContract.MyCityEntry.CONTENT_URI, 
      cityValuesArr); 
} 

@Override 
public Loader<Cursor> onCreateLoader(int id, Bundle args){ 
    return new CursorLoader(getActivity(), 
      MyCityContract.MyCityEntry.CONTENT_URI, 
      null, 
      null, 
      null, 
      null); 
} 

@Override 
public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 
    myCityAdpapter.swapCursor(data); 
} 

@Override 
public void onLoaderReset(Loader<Cursor> loader){ 
    myCityAdpapter.swapCursor(null); 
    } 
} 

我读了onCreateView(......)我的片段

@Override 
public void onActivityCreated(@Nullable Bundle savedInstanceState) { 
    Cursor c = 
      getActivity().getContentResolver().query(MyCityContract.MyCityEntry.CONTENT_URI, 
        new String[]{MyCityContract.MyCityEntry._ID}, 
        null, 
        null, 
        null); 
    if (c.getCount() == 0){ 
     insertData(); 
    } 
    // initialize loader 
    getLoaderManager().initLoader(CURSOR_LOADER_ID, null, this); 
    super.onActivityCreated(savedInstanceState); 
} 

方法里面的光标,这是我在哪里抛出的空指针异常。

任何想法?

谢谢,

泰奥。

编辑

我改变了这种状况,如果从

if (c.getCount() == 0){ 
     insertData(); 
    } 

if (c == null){ 
     insertData(); 
    } 

和我得到这个例外!

Caused by: java.lang.IllegalArgumentException: Unknown URL content://theo.testing.customloaders/my_city 

所以提供者有一个错误。嗯...

+0

如果你移动你的逻辑上'onActivityCreated'到'onViewCreated'?可能内容解析器还不可用 –

+0

仍然有同样的问题:( – Theo

+0

你有没有在init的时候使用cursor cursor.moveToFirst()?? – Vij

回答

1

我想你已经在你的MainActivity片段 getActivity在onActivityCreated使用getActivity因为活动如果得到从内onActivityCreated称为“可能”返回null ......尤其是在像方向变化的配置变化的问题摧毁... 在初始化移动到onAttach ... 以下链接帮我找出 getActivity return null in fragment onActivityCreated in some rooted device

+0

还没有。 – Theo

+0

你的调试指针会进入MY_CITY或MY_CITY_WITH_ID Case中查询吗? –

1

确定。我修好了它。我所做的只是从

theo.testing.customloaders 

改变我的权威名字

theo.testing.customloaders.app 
相关问题