【问题标题】:Filtering ListView by 'selection' parameter in CursorLoader通过 CursorLoader 中的“选择”参数过滤 ListView
【发布时间】:2012-10-11 12:20:48
【问题描述】:

要么我的语法不正确,要么我还不了解 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 正在发生,因为我在调用 btn_logbook_date.setText() 方法之前调用了 fillData() 方法(用于填充我的 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 方法并转换为与上述相同的格式,因此保存的字符串和按钮上显示的文本应该匹配。

更新

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

【问题讨论】:

  • 在您展示的两个示例中,究竟是哪一行抛出了NullPointerException
  • Luksprog,分别是 String[] selectDateString selectDate 行,但感谢 CL,我意识到这是因为我在 btn_logbook_date.setText() 方法之前调用了 fillData() 方法。现在已排序,见上文。
  • 这是使用一些打印语句/调试来查看您的应用程序的逻辑是否遵循您想要的路径的好时机。有很多事情可能不正确,无法提供答案。你没有说你在fillData方法中做了什么,提供者的查询方法看起来如何等等。
  • @Ronnie 我想问一下,当您将某项添加到列表时,您重新打开活动后列表会更改吗?您如何解决这个问题以便立即更新列表?
  • 抱歉,JCodex,我已经有 2 年没写代码了。我不记得了。

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


【解决方案1】:

btn_logbook_datebtn_logbook_date.getText()null

【讨论】:

    【解决方案2】:

    如上所示,我的 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);
    }
    

    【讨论】:

      【解决方案3】:

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

      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};
      

      【讨论】:

      • 传递 null 应该获取所有列。我也已经对此进行了测试,因为我需要使用所有列。
      • 您可以尝试以下方法吗:final String selection = AddDBHelper.KEY_DATE + "=?"; final String[] selectionArgs = { btn_logbook_date.getText().toString() }; CursorLoader cl = new CursorLoader(this, DBProvider.CONTENT_URI, null, selection, selectionArgs, null); return cl;
      • 仍然在第 196 行导致 NullPointerException; String[] selectionArgs
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多