【问题标题】:Refresh a ListView with a cursor with new data from DB使用来自 DB 的新数据的游标刷新 ListView
【发布时间】:2012-04-02 10:00:20
【问题描述】:

我在刷新 ListView 时遇到问题。我调用我的ListViewActivity,我使用带有游标的 SQL 语句从 DB 中获取数据,我使用自定义适配器(扩展 BaseAdapter)绘制 ListView,一切正常。

我想在顶部放置一个EditText 以在我的ListView 上搜索项目,过滤实际视图,相同的活动,输入文本。我 getText() 来自 EditText,并使用此文本创建一个新的 SQL 语句过滤结果。我检查了游标是否有正确的过滤结果,但我使用adapter.notifyDataSetChanged() 尝试更新ListView 但没有任何反应(没有错误或强制关闭)。

谁能帮助我或告诉我一些技巧来获得这个与数据库一起使用的简单搜索功能?我发现很多与ArrayLists + getFilter() + SimpleCursorAdapter 类似的问题,但它不适用于我的数据库和自定义适配器。

活动 ListaCaracteres:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(es.hsk.ap.R.layout.lista_caracteres);

    try{
        hanyuDBHelper = new HanyuSQLHelper(this);
        hanyuDB = hanyuDBHelper.getReadableDatabase();
        c = hanyuDB.rawQuery(" SELECT * FROM Caracteres ", null);
    }
    catch(SQLiteException ex)
    {
        Toast mensajeError=Toast.makeText(getApplicationContext(), "Error accediendo a los datos", Toast.LENGTH_SHORT);
        mensajeError.show();
        Log.e("LogLugares", "Error en getReadableDatabase()", ex);
    }


    adapter = new AdapterListaCaracteres(this,c);
    listaCaracteres = (ListView)findViewById(es.hsk.ap.R.id.listaCaracteres);
    listaCaracteres.setAdapter(adapter);

    buscador = (EditText)findViewById(R.id.buscador);
    buscador.addTextChangedListener(new TextWatcher()
    {
        @Override
        public void onTextChanged( CharSequence arg0, int arg1, int arg2, int arg3)
        {
        }

        @Override
        public void beforeTextChanged( CharSequence arg0, int arg1, int arg2, int arg3)
        {
            // TODO Auto-generated method stub

        }

        @Override
        public void afterTextChanged(Editable arg0)
        {
            // TODO Auto-generated method stub

            String texto="";
            texto=buscador.getText().toString();

            c = hanyuDB.rawQuery(" SELECT * FROM Caracteres WHERE significado LIKE '%"+texto+"%'", null);
            adapter.notifyDataSetChanged();
        }
    });
}

我的自定义适配器,AdapterListaCaracteres 扩展自 BaseAdapter:

public class AdapterListaCaracteres extends BaseAdapter implements ListAdapter{

private Context  mContext;
private Cursor  datos;
private LayoutInflater inflater;

public AdapterListaCaracteres(Context  context, Cursor  c){
    this.mContext = context;
    this.datos = c;
}

@Override
public int getCount() {
    // TODO Auto-generated method stub
    return datos.getCount();
}

@Override
public Object  getItem(int position) {
    // TODO Auto-generated method stub
    return datos.getString(position);
}

@Override
public long getItemId(int position) {
    // TODO Auto-generated method stub
    return 0;
}

public View  getView(int position, View  convertView, ViewGroup parent) {
    // TODO Auto-generated method stub

    View item = convertView;
    ViewHolder holder;

    inflater = (LayoutInflater) mContext.getSystemService(Context .LAYOUT_INFLATER_SERVICE);
    datos.moveToPosition(position);

    if(item==null){
        try{
            item = inflater.inflate(es.hsk.ap.R.layout.caracter, null);
        }
        catch(InflateException ex)
        {

        }


        holder = new ViewHolder();
        holder.caracter = (TextView)item.findViewById(es.hsk.ap.R.id.caracter);
        holder.pinyin = (TextView)item.findViewById(es.hsk.ap.R.id.pinyin);
        holder.significado = (TextView)item.findViewById(es.hsk.ap.R.id.significado);

        item.setTag(holder);
    }
    else{
        holder = (ViewHolder)item.getTag();
    }           

    holder.caracter.setText(datos.getString(2));            
    holder.pinyin.setText(datos.getString(3));  
    holder.significado.setText(datos.getString(4));

    return item;

}
static class ViewHolder{
    TextView caracter;
    TextView pinyin;
    TextView significado;
}
}

【问题讨论】:

  • 我认为这个链接会帮助你... stackoverflow.com/questions/6837397/…> 谢谢...
  • 尝试扩展 CursorAdapter 类并使用此构造函数developer.android.com/reference/android/support/v4/widget/…
  • 我尝试更改为 CursorAdapter,ListView 工作正常,但仍然没有刷新。我已经尝试过 requery() 游标,没有任何反应,adapter.changeCursor(newCursor) 抛出异常“尝试在关闭 SQLiteClosable 上获取引用”,但我没有关闭任何 SQL 对象......我很惊讶有多难更新一个简单的 ListView :( 谢谢
  • 也尝试了 AsyncTask,但我没有看到将 adapter.notifyDataSetChanged() 调用到活动中发生任何事情,同样如此。我还在 Android 2.1、2.2 和 4.0 上运行了该程序,可能存在错误(对此有很多问题,但没有明确的答案)。

标签: android database listview refresh adapter


【解决方案1】:

试试这个:

/*
 * Listener que actuará cuando se escriba en el EditText
 */
buscador.setOnKeyListener(new OnKeyListener() {

    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        // TODO Auto-generated method stub
        String texto = "";
        texto = buscador.getText().toString();
        c = hanyuDB.rawQuery(" SELECT * FROM Caracteres WHERE significado LIKE '%"                                                                                         + texto + "%'", null);

        AdapterListaCaracteres adapter2 = new AdapterListaCaracteres(getApplicationContext(), c, false);
        listaCaracteres.setAdapter(adapter2);
        return false;
    }

});
/*********************************************/

祝你好运;)

亚历克斯

【讨论】:

    【解决方案2】:

    现在它开始工作了!我的一个朋友(感谢 Muni!)找到了一种更好的方法来使用 EditText 动态过滤列表视图结果:

    buscador.setOnKeyListener(new OnKeyListener() {
    
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
    

    代替:

    buscador.addTextChangedListener(new TextWatcher()
    {
    

    感谢所有人的帮助。

    编辑:

    更新@AlexMuni 和我自己的答案,onKey() 方法在模拟器上完美运行,但在真实设备中无法正常运行。

    我终于用之前的方法完美完成了:

    buscador = (EditText)findViewById(R.id.buscador); 
        buscador.addTextChangedListener(new TextWatcher()
        {
            @Override
            public void onTextChanged( CharSequence arg0, int arg1, int arg2, int arg3)
            {
                texto = buscador.getText().toString();
                c = hanyuDB.rawQuery(
                        " SELECT * FROM Caracteres WHERE significado LIKE '%"
                                + texto + "%'", null);
                AdapterListaCaracteres adapter2 = new AdapterListaCaracteres(ListaCaracteres.this, c, false);
                listaCaracteres.setAdapter(adapter2);
            }
    
            @Override
            public void beforeTextChanged( CharSequence arg0, int arg1, int arg2, int arg3)
            {
            }
    
            @Override
            public void afterTextChanged(Editable arg0)
            {
            }
        });     
    

    【讨论】:

      【解决方案3】:

      重新初始化适配器而不是notifydatasetchanged():

          adapter = new AdapterListaCaracteres(this,c);
          listaCaracteres.setAdapter(adapter);
      

      【讨论】:

      • 谢谢,但如果我这样做,我会获得强制关闭,LogCat: 04-02 10:19:53.984: E/AndroidRuntime(565): Uncaught handler: thread main exiting 由于未捕获异常04-02 10:19:54.004: E/AndroidRuntime(565): java.lang.NullPointerException 04-02 10:19:54.004: E/AndroidRuntime(565): 在 es.hsk.ap.caracteres.AdapterListaCaracteres.getView( AdapterListaCaracteres.java:56) 04-02 10:19:54.004: E/AndroidRuntime(565): 在 android.widget.AbsListView.obtainView(AbsListView.java:1274) 04-02 10:19:54.004: E/AndroidRuntime( 565): 在 android.widget.ListView.measureHeightOfChildren(ListView.java:1147)
      • 然后将适配器设置为空一次,然后重新初始化它
      • 我试图将适配器设置为空,但是当我尝试设置适配器时,它会抛出相同的 NullPointerException。我也试过把ListView.setAdapter(null),然后setAdapter(adapter),但是一样:(
      猜你喜欢
      • 2023-03-13
      • 2011-10-11
      • 2014-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-29
      相关资源
      最近更新 更多