SQLite
 sql >> Base de Dados >  >> RDS >> SQLite

Excluindo item de ListView e banco de dados com OnItemClickListener


Resumindo, você precisa ser capaz de distinguir uma linha para exclusão pelos dados disponíveis para o ListView. Se o valor recuperado do cursor, como a 2ª coluna (ou seja, a String extraída usando res.getString(1)) , e o valor será único , você pode recuperá-lo e usá-lo para a exclusão.

No entanto, existem alguns problemas, usando um ListAdapter provavelmente não será suficiente. Existem outros adaptadores, como um ArrayAdapter que oferece mais recursos e, principalmente, um notifyDatasetChanged método (que irá atualizar o ListView associado).

É um desperdício criar um novo adaptador para cada iteração do cursor. Portanto, o adaptador deve ser criado fora do loop e apenas uma vez.

Eu sugiro que a exclusão no clique do item será muito propensa a cliques acidentais, a exclusão no item LongClick seria muito menos propensa à exclusão acidental.

Se você mover variáveis ​​para serem variáveis ​​de classe, não precisará declará-las como finais.

Então, com base no acima, você poderia ter:-

Método do adaptador de matriz

public class ZeigeFaecherListe extends AppCompatActivity {

    DatabaseHelper myDb;
    Cursor res;
    ListView listViewFaecher;
    ArrayAdapter<String> fachListAdapter;
    ArrayList<String> faecherListe;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.zeige_faecher);

        listViewFaecher = (ListView) this.findViewById(R.id.listview);
        myDb = new DatabaseHelper(this);
        addSomeData(); //<<<<<<<<<< ADDED for testing

        faecherListe = new ArrayList<>();
        res = myDb.zeigeFaecher();
        while (res.moveToNext()) {
            faecherListe.add(res.getString(1));
        }

        //<<<< NOTE outside of the loop as this only needs to be done once
        fachListAdapter = new ArrayAdapter<String>(
                this,
                android.R.layout.simple_list_item_1,
                faecherListe
        );
        listViewFaecher.setAdapter(fachListAdapter);

        //<<<<< NOTE used LONG CLICK listener (less likely to accidentally delete)
        listViewFaecher.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                myDb.deleteRow((String)fachListAdapter.getItem(position));
                faecherListe.remove(position);
                fachListAdapter.notifyDataSetChanged(); 
                return true; //<<<< Indicate that this longclick has been used
            }
        });
    }

    private void addSomeData() {
        for (int i=1; i <= 10; i++) {
            myDb.addRow("Row " + String.valueOf(i));
        }
    }
}

Junto com o acima, o deletRow método é:-
public int deleteRow(String col2) {
    SQLiteDatabase db = this.getWritableDatabase();
    return db.delete(TB001,COL_TB001_DATA + "=?",new String[]{col2});
}
  • onde
    • TB001 é uma String constante que é definida para o nome da tabela.
    • COL_TB001_DATA é o nome da coluna da 2ª coluna.

AVISO A solução acima só funcionará corretamente se a 2ª coluna contiver dados exclusivos, caso contrário, várias linhas serão excluídas.

Há também a suposição de que a exclusão funciona, poderia ser melhor ter:-
        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
            if (myDb.deleteRow((String)fachListAdapter.getItem(position))<0) {
                faecherListe.remove(position);
            }
            fachListAdapter.notifyDataSetChanged(); 
            return true; //<<<< Indicate that this longclick has been used
        }

Método do adaptador de cursor


No entanto, existem outros adaptadores adequados para Cursores que podem dispensar a necessidade de um Array intermediário. Você pode utilizar um CursorAdapter . Para um CursorAdapter um nome de coluna _id é obrigatório e esta coluna deve ser longa e também identificar de forma estranha a linha. A intenção e, portanto, o nome é que um alias do rowid é usado (daí também porque o CONSTANT BaseColumns._ID existe).

Um alias do rowid é criado definindo ?? INTEGER PRIMARY KEY Onde ?? é o nome da coluna. Então, idealmente, a tabela deve ser definida incluindo uma definição de coluna com _id INTEGER PRIMARY KEY por exemplo. CREATE mytable (_id INTEGER PRIMARY KEY, myothercolumn TEXT) (você pode seguir INTEGER PRIMARY KEY com a palavra-chave AUTOINCREMENT, no entanto, geralmente você não faria isso, pois tem overheads SQLite Autoincrement)

Se sua tabela não tiver essa coluna, você sempre poderá criar uma coluna no cursor ao consultar os dados, usando rowid AS _id por exemplo. se você SQL equivale a SELECT * FROM mytable então você pode usar SELECT *, rowid AS _id FROM mytable .

Neste exemplo, o estoque SimpleCursorAdapter será usado, o código pode ser:-
public class ZeigeFaecherListe extends AppCompatActivity {

    DatabaseHelper myDb;
    Cursor res;
    ListView listViewFaecher;
    SimpleCursorAdapter fachSimpleCursorAdapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.zeige_faecher);

        listViewFaecher = (ListView) this.findViewById(R.id.listview);
        myDb = new DatabaseHelper(this);
        addSomeData(); //<<<<<<<<<< ADDED for testing

        faecherListe = new ArrayList<>();
        res = myDb.zeigeFaecher();
        fachSimpleCursorAdapter = new SimpleCursorAdapter(this,
                android.R.layout.simple_list_item_1, //<<<< The layout
                res, //<<<< The Cursor
                new String[]{"_data"}, //<<<< The column names from which to get the data
                new int[]{android.R.id.text1} //<<<< The ids of the views in which the data is placed
                );
        listViewFaecher.setAdapter(fachSimpleCursorAdapter);
        listViewFaecher.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                // id is the value of the respective _id column
                //<<<< Normally you would have the delete method in the Databasehelper >>>>
                myDb.getWritableDatabase().delete("mytable","_id=?",new String[]{String.valueOf(id)});
                fachSimpleCursorAdapter.swapCursor(myDb.zeigeFaecher()); // Tell the adapter about the new cursor
                return true;
            }
        });
    }
}

OBSERVAÇÃO como o _id coluna será sempre exclusiva, este método excluirá apenas a linha específica, não várias linhas, se os valores exibidos não forem exclusivos.