Cursor对象返回null

时间:2015-11-19 00:18:38

标签: android sqlite cursor

ANSWER

@Override
public void categoryLoadComplete(Cursor cursor) {
    data = cursor;
    categoryAdapter.swapCursor(cursor);
    categoryAdapter.notifyDataSetChanged();
}

@Override
public void transactionLoadComplete(Cursor cursor) {
    data = cursor;
    categoryAdapter.swapCursor(cursor);
    categoryAdapter.notifyDataSetChanged();
}

原始帖子

我已经在这几个小时了,我似乎无法弄明白,但我已经将问题缩小到我的Cursor对象返回null的事实。我无法弄清楚为什么,并希望在这个网站上寻求更有经验的编码员的帮助。

我从SQLite的这个教程中借用了一个数据库包:http://partisanapps.com/2015/08/really-useful-notes-saving-and-loading-with-a-local-database-i/

我添加了第二个表,并为新表添加了Add,Load,Delete和Save类。

我可以通过导出文件并在SQLite Broweser中查看数据来确认数据库中有数据。

我正在尝试使用数据库中的数据填充微调器,如AddTransaction.class

中所示

感谢您的时间。

AddTransaction.class:

public class AddTransaction extends AppCompatActivity
    implements CategoryLoad.categoryLoadComplete,
    TransactionLoad.LoadComplete {

Spinner currencySpinner, recurringSpinner;
EditText itemName, itemPrice, itemNote;
Time today = new Time(Time.getCurrentTimezone());
Snackbar snackbar;
private Cursor data = null;
LinearLayout transactionLayout;
SimpleCursorAdapter categoryAdapter;

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

    transactionLayout = (LinearLayout) findViewById(R.id.transactionLayout);
    itemName = (EditText) findViewById(R.id.itemName);
    itemPrice = (EditText) findViewById(R.id.itemPrice);
    itemNote = (EditText) findViewById(R.id.note);

    Toolbar toolbar = (Toolbar) findViewById(R.id.app_bar);
    setSupportActionBar(toolbar);
    getSupportActionBar().setTitle("Add a Transaction");
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    CategoryLoad categoryLoad = new CategoryLoad(this);
    categoryLoad.execute();
    categoryAdapter = new SimpleCursorAdapter(getBaseContext(),
            android.R.layout.simple_spinner_item,
            data,
            new String[] {DatabaseHelper.CATEGORY_NAME},
            new int[] {android.R.id.text1},
            0);
    final Spinner categorySpinner = (Spinner) findViewById(R.id.categorySpinner);
    categoryAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    categoryAdapter.swapCursor(data);
    categoryAdapter.notifyDataSetChanged();
    categorySpinner.setAdapter(categoryAdapter);

    currencySpinner = (Spinner) findViewById(R.id.currencySpinner);
    ArrayAdapter<CharSequence> currencyAdapter = ArrayAdapter.createFromResource(this,
            R.array.currency, android.R.layout.simple_spinner_item);
    currencyAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    currencySpinner.setAdapter(currencyAdapter);

    recurringSpinner = (Spinner) findViewById(R.id.recurringSpinner);
    ArrayAdapter<CharSequence> recurringAdapter = ArrayAdapter.createFromResource(this,
            R.array.recurring, android.R.layout.simple_spinner_item);
    recurringAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    recurringSpinner.setAdapter(recurringAdapter);

    if (data == null) {
        snackbar.make(transactionLayout, "Category data failed to load", Snackbar.LENGTH_LONG)
                .setAction("Action", null).show();
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_add_category, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    itemPrice = (EditText) findViewById(R.id.itemPrice);
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }
    if (id == R.id.delete) {
        Toast.makeText(getBaseContext(), "Transaction data lost!", Toast.LENGTH_LONG).show();
        NavUtils.navigateUpFromSameTask(this);
        return true;
    }

    if (id == R.id.save) {
        if (TextUtils.isEmpty(itemPrice.getText().toString())) {
            snackbar.make(transactionLayout, "Please input a price.", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        } else {
            today.setToNow();
            TransactionAdd transactionAdd = new TransactionAdd(this);
            transactionAdd.execute(
                    itemName.getText().toString(),
                    itemPrice.getText().toString(),
//                      categorySpinner.getSelectedItem().toString(),
                    null,
                    currencySpinner.getSelectedItem().toString(),
                    recurringSpinner.getSelectedItem().toString(),
                    itemNote.getText().toString(),
                    today.format("%Y-%m-%d %H:%M:%S")
            );
            Toast.makeText(getBaseContext(), "Transaction added!", Toast.LENGTH_LONG).show();
            NavUtils.navigateUpFromSameTask(this);
        }

        return true;
    }

    return super.onOptionsItemSelected(item);
}

@Override
public void categoryLoadComplete(Cursor cursor) {
    data = cursor;
}

@Override
public void transactionLoadComplete(Cursor cursor) {

}
}

CategoryLoad:

public class CategoryLoad extends AsyncTask<Void, Void, Cursor> {

private static final String TAG = "LoadTask";
private categoryLoadComplete loadComplete;
private WeakReference<Context> categoryWeakReference;
private DatabaseHelper db;

public interface categoryLoadComplete {
    void categoryLoadComplete(Cursor cursor);
}

public CategoryLoad(Context context) {
    categoryWeakReference = new WeakReference<>(context);
    db = DatabaseHelper.getInstance(categoryWeakReference.get());
    try {
        loadComplete = (categoryLoadComplete) categoryWeakReference.get();
    } catch (ClassCastException e) {
        Log.e(TAG, context.toString() + " must implement LoadComplete");
    }
}

@Override
protected Cursor doInBackground(Void... params) {
    Cursor result = db.getReadableDatabase().query(
            DatabaseHelper.CATEGORIES_TABLE,
            null, null, null, null, null, DatabaseHelper.CATEGORY_KEY_ID);
    result.getCount();
    return result;
}

@Override
protected void onPreExecute() {
}

@Override
protected void onPostExecute(Cursor cursor) {
    loadComplete.categoryLoadComplete(cursor);
}
}

TransactionLoad:

public class TransactionLoad extends AsyncTask<Void, Void, Cursor> {

private static final String TAG = "LoadTask";
private LoadComplete loadComplete;
private WeakReference<Context> transactionWeakReference;
private DatabaseHelper tt;

public interface LoadComplete {
    void transactionLoadComplete(Cursor cursor);
}

public TransactionLoad(Context context) {
    transactionWeakReference = new WeakReference<>(context);
    tt = DatabaseHelper.getInstance(transactionWeakReference.get());
    try {
        loadComplete = (LoadComplete) transactionWeakReference.get();
    } catch (ClassCastException e) {
        Log.e(TAG, context.toString() + " must implement LoadComplete");
    }
}

@Override
protected Cursor doInBackground(Void... params) {
    Cursor result = tt.getReadableDatabase().query(
            DatabaseHelper.TRANSACTIONS_TABLE,
            null, null, null, null, null, DatabaseHelper.TRANSACTION_KEY_ID);
    result.getCount();
    return result;
}

@Override
protected void onPreExecute() {
}

@Override
protected void onPostExecute(Cursor cursor) {
    loadComplete.transactionLoadComplete(cursor);
}
}

DatabaseHelper:

public class DatabaseHelper extends SQLiteOpenHelper {

private static final String DATABASE_NAME = "budgets.db";
private static final int SCHEMA = 1;
public static final String KEY_ID = "_id";
//  ~~~~~~~~~~~~~~~~~~~Categories~~~~~~~~~~~~~~~~~~~~~~~~~~~
public static final String CATEGORIES_TABLE = "categories";
//  ~~~~~~~~~~~~~~~~~~~~~Columns~~~~~~~~~~~~~~~~~~~~~~~~~~~
public static final String CATEGORY_KEY_ID = "_id_cat";
public static final String CATEGORY_NAME = "cat_name";
public static final String CATEGORY_AMOUNT = "cat_amount";
public static final String CATEGORY_CURRENCY = "cat_currency";
public static final String CATEGORY_FREQUENCY = "cat_frequency";
public static final String CATEGORY_DURATION_VALUE = "cat_duration_value";
public static final String CATEGORY_DURATION_MODIFIER = "cat_duration_modifier";
public static final String CATEGORY_OVERAGE = "cat_overage";
public static final String CATEGORY_SURPLUS = "cat_surplus";
public static final String CATEGORY_DATE = "cat_date";

//  ~~~~~~~~~~~~~~~~~~~Transactions~~~~~~~~~~~~~~~~~~~~~~~~~~~
public static final String TRANSACTIONS_TABLE = "transactions";
//  ~~~~~~~~~~~~~~~~~~~~~Columns~~~~~~~~~~~~~~~~~~~~~~~~~~~
public static final String TRANSACTION_KEY_ID = "_id_trans";
public static final String TRANSACTION_NAME = "trans_name";
public static final String TRANSACTION_PRICE = "trans_price";
public static final String TRANSACTION_CATEGORY = "trans_category";
public static final String TRANSACTION_CURRENCY = "trans_currency";
public static final String TRANSACTION_RECURRING = "trans_recurring";
public static final String TRANSACTION_NOTES = "trans_notes";
public static final String TRANSACTION_DATE = "trans_date";

private static DatabaseHelper mInstance = null;

public static synchronized DatabaseHelper getInstance(Context context) {
    if (mInstance == null) {
        mInstance = new DatabaseHelper(context.getApplicationContext());
    }
    return mInstance;
}

public DatabaseHelper(Context context) {
    super(context, DATABASE_NAME, null, SCHEMA);
}

public DatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory,
                      int version) {
    super(context, name, factory, version);
}

@Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL("CREATE TABLE categories (_id_cat INTEGER PRIMARY KEY AUTOINCREMENT, " +
            "cat_name TEXT, cat_amount TEXT, cat_currency TEXT, cat_frequency TEXT," +
            "cat_duration_value TEXT, cat_duration_modifier TEXT, cat_overage TEXT, " +
            "cat_surplus TEXT, cat_date TEXT);");
    db.execSQL("CREATE TABLE transactions (_id_trans INTEGER PRIMARY KEY AUTOINCREMENT, " +
            "trans_name TEXT, trans_price TEXT, trans_category TEXT, trans_currency TEXT, " +
            "trans_recurring TEXT, trans_notes TEXT, trans_date TEXT, " +
            "FOREIGN KEY(trans_category) REFERENCES categories(cat_name));");
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    int upgradeTo = oldVersion + 1;
    while (upgradeTo <= newVersion) {
        switch (upgradeTo) {
            case 2:
                break;
        }
        upgradeTo++;
    }
}
}

2 个答案:

答案 0 :(得分:1)

您需要在categoryLoadComplete()和transactionLoadComplete()方法中将光标设置在适配器上,然后调用adapter.notifyDataSetChanged()。

答案 1 :(得分:1)

您的光标为空,因为如果您的适配器关闭,则在您通过时尚未分配它。在&#34; categoryLoadComplete&#34;。

之前,请尝试不要创建适配器
@Override
public void categoryLoadComplete(Cursor cursor) {
    data = cursor;
    categoryAdapter = new SimpleCursorAdapter(this,
        android.R.layout.simple_spinner_item,
        data,
        new String[] {DatabaseHelper.CATEGORY_NAME},
        new int[] {android.R.id.text1},
        0);
    categorySpinner.setAdapter(categoryAdapter);
}