我的使用Content Provider和CursorLoader的库存应用程序在启动

时间:2017-05-24 09:47:08

标签: android android-sqlite android-contentprovider android-cursorloader

我是初学程序员,我被分配了一个项目来制作库存应用程序。该应用程序使用Content Provider和Cursor Loader;在我实现了Content Provider和CurorLoader后,它曾经工作正常,但是,当我尝试将图像添加到listview中的项目时,它在启动时开始崩溃。

这是DbHelper类:

public class InventoryDbHelper extends SQLiteOpenHelper {

public static final String LOG_TAG = InventoryDbHelper.class.getSimpleName();

private static final String DATABASE_NAME = "inventory.db";

private static final int DATABASE_VERSION = 1;

public InventoryDbHelper(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);

}

@Override
public void onCreate(SQLiteDatabase db) {

    String SQL_CREATE_INVENTORY_TABLE = "CREATE TABLE " + InventoryEntry.TABLE_NAME + " ("
            + InventoryEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
            + InventoryEntry.COLUMN_INVENTORY_NAME + " TEXT NOT NULL, "
            + InventoryEntry.COLUMN_INVENTORY_SUPPLIER + " TEXT NOT NULL, "
            + InventoryEntry.COLUMN_INVENTORY_PRICE + " INTEGER NOT NULL, "
            + InventoryEntry.COLUMN_INVENTORY_QUANTITY + " INTEGER NOT NULL DEFAULT 0, "
            + InventoryEntry.COLUMN_INVENTORY_IMAGE + " TEXT NOT NULL DEFAULT 'No images', "
            + ");";

    db.execSQL(SQL_CREATE_INVENTORY_TABLE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("DROP TABLE IF EXISTS " + InventoryEntry.TABLE_NAME);
    onCreate(db);
}

这是合同:

public final class InventoryContract {

private InventoryContract() {}

public static final String CONTENT_AUTHORITY = "com.mesharialmutairi.inventoryapp";

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

public  static final String PATH_INVENTORIES = "inventories";

public static final class InventoryEntry implements BaseColumns {

    public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, PATH_INVENTORIES);

    public static final String CONTENT_LIST_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_INVENTORIES;

    public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_INVENTORIES;

    public final static String TABLE_NAME = "inventories";

    public final static String _ID = BaseColumns._ID;

    public final static String COLUMN_INVENTORY_IMAGE = "image";

    public final static String COLUMN_INVENTORY_NAME = "name";

    public final static String COLUMN_INVENTORY_SUPPLIER = "supplier";

    public final static String COLUMN_INVENTORY_PRICE = "price";

    public final static String COLUMN_INVENTORY_QUANTITY = "quantity";

    public static Uri buildInventoryURI(long id) {
        return ContentUris.withAppendedId(CONTENT_URI, id);
    }

}

这是提供者:

public class InventoryProvider extends ContentProvider{

public static final String TAG = InventoryProvider.class.getSimpleName();

private static final int INVENTORIES = 100;

private static final int INVENTORY_ID = 101;

private static final UriMatcher iUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

static {

    iUriMatcher.addURI(InventoryContract.CONTENT_AUTHORITY, InventoryContract.PATH_INVENTORIES, INVENTORIES);

    iUriMatcher.addURI(InventoryContract.CONTENT_AUTHORITY, InventoryContract.PATH_INVENTORIES + "/#", INVENTORY_ID);
}

private InventoryDbHelper inventoryDbHelper;

@Override
public boolean onCreate() {
    Log.i(TAG, "DB helper is prepared");
    inventoryDbHelper = new InventoryDbHelper(getContext());
    return true;
}

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {

    SQLiteDatabase database = inventoryDbHelper.getReadableDatabase();

    Cursor cursor;

    int match = iUriMatcher.match(uri);
    switch (match) {
        case INVENTORIES:
            cursor = database.query(InventoryEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
            break;

        case INVENTORY_ID:
            selection = InventoryEntry._ID + "=?";
            selectionArgs = new String[] { String.valueOf(ContentUris.parseId(uri)) };

            cursor = database.query(InventoryEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
            break;
        default:
            throw new IllegalArgumentException("Cannot query unknown URI " + uri);
    }

    cursor.setNotificationUri(getContext().getContentResolver(), uri);

    return cursor;
}

@Override
public Uri insert(Uri uri, ContentValues contentValues) {
    final int match = iUriMatcher.match(uri);
    switch (match) {
        case INVENTORIES:
            return insertInventory(uri, contentValues);
        default:
            throw new IllegalArgumentException("Insertion is not supported for " + uri);
    }
}

private Uri insertInventory(Uri uri, ContentValues values) {

    String name = values.getAsString(InventoryEntry.COLUMN_INVENTORY_NAME);
    if (name == null) {
        throw  new IllegalArgumentException("Inventory requires a name");

    }

    String supplier = values.getAsString(InventoryEntry.COLUMN_INVENTORY_SUPPLIER);
    if (supplier == null) {
        throw  new IllegalArgumentException("Inventory requires a supplier");

    }

    Integer price = values.getAsInteger(InventoryEntry.COLUMN_INVENTORY_PRICE);
    if (price != null && price < 0) {
        throw new IllegalArgumentException("Inventory requires a valid price");
    }

    Integer quantity = values.getAsInteger(InventoryEntry.COLUMN_INVENTORY_QUANTITY);
    if (quantity != null && quantity < 0) {
        throw new IllegalArgumentException("Inventory requires a valid quantity");
    }

    SQLiteDatabase database = inventoryDbHelper.getWritableDatabase();

    long id = database.insert(InventoryEntry.TABLE_NAME, null, values);

    if (id == -1) {
        Log.e(TAG, "Failed to insert row for " + uri);
        return null;
    }

    getContext().getContentResolver().notifyChange(uri, null);

    return ContentUris.withAppendedId(uri, id);
}

@Override
public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) {

    final int match = iUriMatcher.match(uri);
    switch (match) {
        case INVENTORIES:
            return updateInventory(uri, contentValues, selection, selectionArgs);
        case INVENTORY_ID:

            selection = InventoryEntry._ID + "=?";
            selectionArgs = new String[] { String.valueOf(ContentUris.parseId(uri)) };
            return updateInventory(uri, contentValues, selection, selectionArgs);
        default:
            throw new IllegalArgumentException("Update is not supported for " + uri);
    }

}

private int updateInventory(Uri uri, ContentValues values, String selection, String[] selectionArgs) {

    if (values.containsKey(InventoryEntry.COLUMN_INVENTORY_NAME)) {
        String name = values.getAsString(InventoryContract.InventoryEntry.COLUMN_INVENTORY_NAME);
        if (name == null) {
            throw new IllegalArgumentException("Inventory requires a name");
        }
    }

    if (values.containsKey(InventoryEntry.COLUMN_INVENTORY_SUPPLIER)) {
        String supplier = values.getAsString(InventoryContract.InventoryEntry.COLUMN_INVENTORY_SUPPLIER);
        if (supplier == null) {
            throw new IllegalArgumentException("Inventory requires a supplier");
        }
    }

    if (values.containsKey(InventoryEntry.COLUMN_INVENTORY_PRICE)) {
        Integer price = values.getAsInteger(InventoryContract.InventoryEntry.COLUMN_INVENTORY_PRICE);
        if (price != null && price < 0) {
            throw new IllegalArgumentException("Inventory requires valid price");
        }
    }

    if (values.containsKey(InventoryEntry.COLUMN_INVENTORY_QUANTITY)) {
        Integer quantity = values.getAsInteger(InventoryEntry.COLUMN_INVENTORY_QUANTITY);
        if (quantity != null && quantity < 0) {
            throw new IllegalArgumentException("Inventory requires valid quantity");
        }
    }

    if (values.size() == 0) {
        return 0;
    }

    SQLiteDatabase database = inventoryDbHelper.getWritableDatabase();

    int rowsUpdated = database.update(InventoryEntry.TABLE_NAME, values, selection, selectionArgs);

    if (rowsUpdated != 0) {
        getContext().getContentResolver().notifyChange(uri, null);
    }

    return  rowsUpdated;
}

@Override
public int delete(Uri uri, String selection, String [] selectionArgs) {
    SQLiteDatabase database = inventoryDbHelper.getWritableDatabase();

    int rowsDeleted;

    final int match = iUriMatcher.match(uri);
    switch (match) {
        case INVENTORIES:
            rowsDeleted = database.delete(InventoryEntry.TABLE_NAME, selection, selectionArgs);
            break;
        case INVENTORY_ID:
            selection = InventoryEntry._ID + "=?";
            selectionArgs = new String[] {String.valueOf(ContentUris.parseId(uri)) };
            rowsDeleted = database.delete(InventoryEntry.TABLE_NAME, selection,selectionArgs);
            break;
        default:
            throw new IllegalArgumentException("Deletion is not supported for " + uri);
    }

    if (rowsDeleted != 0) {
        getContext().getContentResolver().notifyChange(uri, null);
    }

    return rowsDeleted;
}

@Override
public String getType(Uri uri) {
    final int match = iUriMatcher.match(uri);
    switch (match) {
        case INVENTORIES:
            return InventoryEntry.CONTENT_LIST_TYPE;
        case INVENTORY_ID:
            return InventoryEntry.CONTENT_ITEM_TYPE;
        default:
            throw new IllegalArgumentException("Unknown URI " + uri + " with match " + match);
    }
}

这是MainActivity:

public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {


private static final int INVENTORY_LOADER = 0;

InventoryCursorAdapter iCursoradapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(MainActivity.this, EditorActivity.class);
            startActivity(intent);
        }
    });

    ListView inventoryListView = (ListView) findViewById(R.id.list);

    View emptyView = findViewById(R.id.empty_view);
    inventoryListView.setEmptyView(emptyView);

    iCursoradapter = new InventoryCursorAdapter(this, null);
    inventoryListView.setAdapter(iCursoradapter);

    inventoryListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
            Intent intent = new Intent(MainActivity.this, EditorActivity.class);

            Uri currentInventoryUri = ContentUris.withAppendedId(InventoryEntry.CONTENT_URI, id);

            intent.setData(currentInventoryUri);

            startActivity(intent);
        }
    });

    getLoaderManager().initLoader(INVENTORY_LOADER, null, this);
}

private void insertInventory() {

    ContentValues values = new ContentValues();
    values.put(InventoryEntry.COLUMN_INVENTORY_NAME, "Sunglasses");
    values.put(InventoryEntry.COLUMN_INVENTORY_SUPPLIER, "Elegance");
    values.put(InventoryEntry.COLUMN_INVENTORY_PRICE, "75");
    values.put(InventoryEntry.COLUMN_INVENTORY_QUANTITY, "3");

    Uri newUri = getContentResolver().insert(InventoryEntry.CONTENT_URI, values);

}

private void deleteAllInventories() {

    int rowsDeleted = getContentResolver().delete(InventoryEntry.CONTENT_URI, null, null);
    Log.v("MainActivity", rowsDeleted + " rows deleted from inventory database");

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    getMenuInflater().inflate(R.menu.menu_catalog, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) {

        case R.id.action_insert_dummy_data:
            insertInventory();
            return true;
        case R.id.action_delete_all_entries:
            deleteAllInventories();
            return true;
    }
    return super.onOptionsItemSelected(item);

}

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {

    String[] projection = {
            InventoryEntry._ID,
            InventoryEntry.COLUMN_INVENTORY_NAME,
            InventoryEntry.COLUMN_INVENTORY_SUPPLIER,
            InventoryEntry.COLUMN_INVENTORY_PRICE,
            InventoryEntry.COLUMN_INVENTORY_QUANTITY,
            InventoryEntry.COLUMN_INVENTORY_IMAGE};

    return new CursorLoader(this, InventoryEntry.CONTENT_URI, projection, null, null, null);

}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {

    iCursoradapter.swapCursor(data);
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {

    iCursoradapter.swapCursor(null);
}

这是CursorAdapter:

public class InventoryCursorAdapter extends CursorAdapter {

private static final String TAG = InventoryCursorAdapter.class.getSimpleName();

public InventoryCursorAdapter(Context context, Cursor c) {

    super(context, c, 0);
}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {

    return LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);
}

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

    TextView nameTextView = (TextView) view.findViewById(R.id.name);
    TextView supplierTextView = (TextView) view.findViewById(R.id.supplier);
    TextView priceTextView = (TextView) view.findViewById(R.id.price);
    TextView quantityTextView = (TextView) view.findViewById(R.id.quantity);
    ImageView imageImageView = (ImageView) view.findViewById(R.id.image);

    int nameColumnIndex = cursor.getColumnIndex(InventoryEntry.COLUMN_INVENTORY_NAME);
    int supplierColumnIndex = cursor.getColumnIndex(InventoryEntry.COLUMN_INVENTORY_SUPPLIER);
    int priceColumnIndex = cursor.getColumnIndex(InventoryEntry.COLUMN_INVENTORY_PRICE);
    int quantityColumnIndex = cursor.getColumnIndex(InventoryEntry.COLUMN_INVENTORY_QUANTITY);
    int imageColumnIndex = cursor.getColumnIndex(InventoryEntry.COLUMN_INVENTORY_IMAGE);

    int id = cursor.getInt(cursor.getColumnIndex(InventoryEntry._ID));
    String inventoryName = cursor.getString(nameColumnIndex);
    String inventorySupplier = cursor.getString(supplierColumnIndex);
    String inventoryPrice = cursor.getString(priceColumnIndex);
    int quantity = cursor.getInt(quantityColumnIndex);
    Uri imageUri = Uri.parse(cursor.getString(imageColumnIndex));

    final Uri currentInventoryUri = ContentUris.withAppendedId(InventoryEntry.CONTENT_URI, id);

    Log.d(TAG, "genero Uri: " + currentInventoryUri + " Inventory name: " + inventoryName + " id: " + id);

    if (TextUtils.isEmpty(inventorySupplier)) {

        inventorySupplier = context.getString(R.string.unknown_supplier);
    }

    nameTextView.setText(inventoryName);
    supplierTextView.setText(inventorySupplier);
    priceTextView.setText(inventoryPrice);
    quantityTextView.setText(quantity);

    Glide.with(context).load(imageUri).placeholder(R.mipmap.ic_launcher).error(ic_insert_placeholder).crossFade().centerCrop().into(imageImageView);

}

2 个答案:

答案 0 :(得分:1)

我最初的想法是删除SQL create table语句中的最后一个逗号。但是您应该从Android监视器检查并共享错误堆栈,如果不能通过该步骤解决,则至少可以识别大多数问题。祝你好运,听起来像你在做Udacity android初学者课程。这很有趣我几乎在下一堂课的一半。保持动力。

答案 1 :(得分:0)

+ InventoryEntry.COLUMN_INVENTORY_IMAGE + " TEXT NOT NULL DEFAULT 'No images', "
            + ");";

尝试将其更改为

+ InventoryEntry.COLUMN_INVENTORY_IMAGE + " TEXT NOT NULL DEFAULT 'No images'");";
相关问题