0

I have a problem refreshing a ListView. I call my ListView Activity, I get the data from DB with a SQL statment with a cursor, I draw the ListView with a custom adapter (extends BaseAdapter), all works fine.

I want to put an EditText on the top to search items on my ListView, filter the actual view, same Activity, with the typed text. I getText() from EditText, and make a new SQL statment filtering the results with this text. I have checked that the cursor has the correct filtered results, but I use adapter.notifyDataSetChanged() trying to update the ListView but nothing happens (no errors or force closes).

Can anyone help me or tell me some tips to obtain this simple search function working with a database? I have found many similar questions with ArrayLists + getFilter() + SimpleCursorAdapter, but it doesn't works with my DB and custom adapter.

Activity 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();
        }
    });
}

My custom adapter, AdapterListaCaracteres extends from 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;
}
}
4
  • I think this link will hwlp you... <stackoverflow.com/questions/6837397/…> Thanks... Commented Apr 2, 2012 at 10:07
  • try extend CursorAdapter class and use this constructor developer.android.com/reference/android/support/v4/widget/… Commented Apr 2, 2012 at 10:57
  • I have tried to change to CursorAdapter, ListView works ok, but it stills no refresh. I have tried requery() cursor, nothing happens, adapter.changeCursor(newCursor) throws exception "attempt to acquire a reference on a close SQLiteClosable", but I don't close any SQL objet... I'm surprised how difficult is to update a simply ListView :( Thanks Commented Apr 2, 2012 at 13:24
  • Also tried AsyncTask, but I don't see anything happens to call adapter.notifyDataSetChanged() there instead into the activity, the same. I have also run the program onto Android 2.1, 2.2, and 4.0, for a possible bug (there are a lot of questions about that, and no clear answer). Commented Apr 2, 2012 at 13:29

3 Answers 3

1

Try this:

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

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

Good Luck ;)

ALEX

Sign up to request clarification or add additional context in comments.

Comments

0

Now it's working! A friend of mine (Thanks Muni!) found a better way to filter a listview result dinamically with EditText:

buscador.setOnKeyListener(new OnKeyListener() {

        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {

instead of:

buscador.addTextChangedListener(new TextWatcher()
{

Thanks all people for your help.

EDIT:

Updating @AlexMuni and my own answer, onKey() method runs perfectly on emulator, but doesn't works fine in real devices.

I finally have done it perfectly with the previous method:

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

Comments

0

Re-initialize the Adapter instead of notifydatasetchanged():

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

3 Comments

Thanks, but if I do that, I obtain a Force Close, LogCat: 04-02 10:19:53.984: E/AndroidRuntime(565): Uncaught handler: thread main exiting due to uncaught exception 04-02 10:19:54.004: E/AndroidRuntime(565): java.lang.NullPointerException 04-02 10:19:54.004: E/AndroidRuntime(565): at es.hsk.ap.caracteres.AdapterListaCaracteres.getView(AdapterListaCaracteres.java:56) 04-02 10:19:54.004: E/AndroidRuntime(565): at android.widget.AbsListView.obtainView(AbsListView.java:1274) 04-02 10:19:54.004: E/AndroidRuntime(565): at android.widget.ListView.measureHeightOfChildren(ListView.java:1147)
then set adapter null once and then reinitialize it
I have tried to put null the adapter, but when I'm trying to setAdapter it throws the same NullPointerException. I have also tried to put ListView.setAdapter(null), and then setAdapter(adapter), but the same :(

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.