通过CursorLoader中的'selection'参数过滤ListView

时间:2012-10-21 14:30:02

标签: android sqlite filter where-clause android-cursorloader

我的语法不正确或者我还没有理解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()方法之前调用了btn_logbook_date.setText()方法(用于填充我的ListView)。我已经在我的活动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方法并转换为与上面相同的格式,因此保存的字符串和按钮上显示的文本应该匹配。

更新

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

3 个答案:

答案 0 :(得分:1)

btn_logbook_datebtn_logbook_date.getText()null

答案 1 :(得分: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);
}

答案 2 :(得分:0)

您传递'null'值作为cursorloader的投影。

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

您需要指定游标加载器应获取的列,例如:

static final String[] ADAPTER_PROJECTION = new String[] {
        AddDBHelper.KEY_DATE,
        AddDBHelper.KEY_NAME,
        AddDBHelper.SOME_OTHER_COLUMN_NAME};