5

我的语法不正确,或者我还不明白 Loaders 是如何工作的,但我目前有一个 ListView 显示我的数据库中的所有项目。该活动有一个显示今天日期的按钮。用户可以单击它来调出日期对话框,或者可以按上一个/下一个按钮来更改显示的日期。我想根据显示的日期过滤 ListView,因此只有保存该日期的记录才会显示。

目前所有记录都显示为

public Loader<Cursor> onCreateLoader(int id, Bundle args) {         
    CursorLoader cl = new CursorLoader(this, DBProvider.CONTENT_URI,
            null, null, null, null);
    return cl;
}

我已经根据我在网上看到的内容尝试了一些变体,但基本上我试图包含一个“选择”,将今天的日期显示为一个字符串(它已经通过 SimpleDateFormatter 并设置为按钮上的文本)。

public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
    String[] selectDate = { btn_logbook_date.getText().toString() };
    CursorLoader cl = new CursorLoader(this, DBProvider.CONTENT_URI,
            null, "Date=?", selectDate , null);
    return cl;
}

public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
    String selectDate = btn_logbook_date.getText().toString();
    String selection = "(" + AddDBHelper.KEY_DATE + "=" + selectDate + ")";

    CursorLoader cl = new CursorLoader(this, DBProvider.CONTENT_URI,
            null, selection, null, null);
    return cl;
}

两者都生成 NullPointerExceptions。任何有关在创建加载程序时过滤此问题的正确方法的指针将不胜感激。

更新

似乎 NullPointerException 正在发生,因为我fillData()在调用我的方法之前调用了该方法(用于填充我的 ListView)btn_logbook_date.setText()。我已经在我的活动中进一步向下移动onCreate,应用程序不再崩溃,但数据不再填充。我意识到如果我用今天的日期保存一条新记录,它会显示在我的列表视图中,但是在更改日期时没有其他记录出现。在 ListView 活动中更改回今天也显示为空白。

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView (R.layout.dash_logbook);     
    this.getListView().setDividerHeight(2);         

    ListView list = getListView();
    list.setOnItemClickListener(this);

    btn_logbook_date = (Button) findViewById(R.id.btn_logbook_date);
    now = Calendar.getInstance();
    nowD = now.getTime();

    SimpleDateFormat dFormatter = new SimpleDateFormat("dd MMM yyyy");
    strDate = dFormatter.format(nowD);
    btn_logbook_date.setText(strDate);              

    fillData();
}

// I have code here to call on the DateDialogFragment

public void updateDatePrev() {
    String prevVar[] = btn_logbook_date.getText().toString().split(" ");

    if (prevVar[1].equalsIgnoreCase("Jan")) {
        lMonth = 0;
    } else if (prevVar[1].equalsIgnoreCase("Feb")) {
        lMonth = 1;
    } else if (prevVar[1].equalsIgnoreCase("Mar")) {
        lMonth = 2;
    } else if (prevVar[1].equalsIgnoreCase("Apr")) {
        lMonth = 3;
    } else if (prevVar[1].equalsIgnoreCase("May")) {
        lMonth = 4;
    } else if (prevVar[1].equalsIgnoreCase("Jun")) {
        lMonth = 5;
    } else if (prevVar[1].equalsIgnoreCase("Jul")) {
        lMonth = 6;
    } else if (prevVar[1].equalsIgnoreCase("Aug")) {
        lMonth = 7;
    } else if (prevVar[1].equalsIgnoreCase("Sep")) {
        lMonth = 8;
    } else if (prevVar[1].equalsIgnoreCase("Oct")) {
        lMonth = 9;
    } else if (prevVar[1].equalsIgnoreCase("Nov")) {
        lMonth = 10;
    } else if (prevVar[1].equalsIgnoreCase("Dec")) {
        lMonth = 11;
    }

    int lYear = Integer.parseInt(prevVar[2]);
    int lDay = Integer.parseInt(prevVar[0]);
    now = Calendar.getInstance();
    now.set(Calendar.YEAR, lYear);
    now.set(Calendar.MONTH, lMonth);
    now.set(Calendar.DAY_OF_MONTH, lDay - 1);
    PrevDate = now.getTime();
    SimpleDateFormat prevDFormatter = new SimpleDateFormat("dd MMM yyyy");
    strDate = prevDFormatter.format(PrevDate);
    btn_logbook_date.setText(strDate);      
}

public void updateDateNext() {
//same code as above, except adding +1 to the days when clicked
}

private void fillData() {
    // Fields from the database (projection) must include
    // the _id column for the adapter to work
    String[] from = new String[] { AddDBHelper.KEY_BGL, AddDBHelper.KEY_ROWID,
            AddDBHelper.KEY_CATEG, AddDBHelper.KEY_TIME };
    // Fields on the UI to which we map
    int[] to = new int[] {R.id.logBGL, R.id.logRowID, R.id.logCateg, R.id.logTime };

    getLoaderManager().initLoader(0, null, this);
    adapter = new SimpleCursorAdapter(this, R.layout.logbook_item, null, from, to, 0);

    setListAdapter(adapter);        
}    

public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
     String selection = AddDBHelper.KEY_DATE + "=?";
     String[] selectionArgs = { String.valueOf(btn_logbook_date.getText().toString()) };

    CursorLoader cl = new CursorLoader(this, DBProvider.CONTENT_URI,
            null, selection, selectionArgs, null);
    return cl;
}

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

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

当最初从不同的活动保存到数据库时,我也在使用该SimpleDateFormat方法并转换为与上面相同的格式,因此保存的字符串和按钮上显示的文本应该匹配。

更新

我已经在下面回答了这个问题。关于重新填充列表的问题将单独询问,因为原始问题仅涉及按日期过滤列表。我通过使用今天的日期创建新记录并在打开列表视图活动时填充它们来确认这是有效的。通过更改 Android 模拟器中的日期,然后重新打开应用程序和列表视图活动,我可以看到属于新设置日期的记录。

4

3 回答 3

1

要么btn_logbook_date要么btn_logbook_date.getText()null

于 2012-10-21T16:00:34.307 回答
1

如上所示,我的fillData()方法在我的活动中被调用onCreate,但在我的按钮上设置日期之前我错误地调用了它。fillData()用于填充列表并初始化我的加载器。加载程序根据我的按钮上显示的日期进行过滤。通过在尝试调用之后设置按钮上的日期fillData(),列表没有从按钮获取的值,从而导致 NullPointerException。

正确的代码在下面再次显示以进行澄清。

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView (R.layout.dash_logbook);     
this.getListView().setDividerHeight(2);         

ListView list = getListView();
list.setOnItemClickListener(this);

btn_logbook_date = (Button) findViewById(R.id.btn_logbook_date);
now = Calendar.getInstance();
nowD = now.getTime();

SimpleDateFormat dFormatter = new SimpleDateFormat("dd MMM yyyy");
strDate = dFormatter.format(nowD);
// Set the text on this button BEFORE calling the fillData() method
btn_logbook_date.setText(strDate);              

fillData();
}

private void fillData() {       
    String[] from = new String[] { AddDBHelper.KEY_BGL, AddDBHelper.KEY_ROWID,
            AddDBHelper.KEY_CATEG, AddDBHelper.KEY_TIME };
    int[] to = new int[] {R.id.logBGL, R.id.logRowID, R.id.logCateg, R.id.logTime };

    getLoaderManager().initLoader(0, null, this);
    adapter = new SimpleCursorAdapter(this, R.layout.logbook_item, null, from, to, 0);

    setListAdapter(adapter);
}

public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
     String selection = AddDBHelper.KEY_DATE + "=?";
     String[] selectionArgs = { String.valueOf(btn_logbook_date.getText().toString()) };

    CursorLoader cl = new CursorLoader(this, DBProvider.CONTENT_URI,
            null, selection, selectionArgs, null);
    return cl;
}

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

public void onLoaderReset(Loader<Cursor> loader) {
    // data is not available anymore; delete reference
    adapter.swapCursor(null);
}
于 2012-10-23T12:59:47.223 回答
0

您正在传递一个“空”值作为光标加载器的投影。

CursorLoader(Context context, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

您需要指定您的 cursorloader 应获取的列,例如:

static final String[] ADAPTER_PROJECTION = new String[] {
        AddDBHelper.KEY_DATE,
        AddDBHelper.KEY_NAME,
        AddDBHelper.SOME_OTHER_COLUMN_NAME};
于 2012-10-21T14:41:29.027 回答