简体   繁体   中英

Android studio listview change item

can anyone help me with changing the name of the item in listview? I don't have an idea how to do it. I am using SQLite database and this is my update name:

public void doneName(String finishedName,int id, String oldName)
    {

        SQLiteDatabase db = this.getWritableDatabase();
        String query = "UPDATE " + TABLE_NAME + " SET " + COL2 + " = '" + finishedName + "' WHERE " + COL1 +
                " = '" + id + "'" + " AND " + COL2 + " = '" + oldName + "'";
        db.execSQL(query );
    }

after that in my activity I have set onItemClickListener where it should change name but it does not, it only shows toast:

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String name = parent.getItemAtPosition(position).toString();
                Cursor cursor =th.getItemID(name);
                int itemID = -1;
                while(cursor.moveToNext())
                {
                    itemID = cursor.getInt(0);
                }
                if(itemID>-1) {
                    String item = "Done";
                    th.doneName(item, selectedID, selectedName);
                    Toast.makeText(HomePageActivity.this, "You have accomplished this task!", Toast.LENGTH_SHORT).show();
                }}
        });

I'm afraid you don't update the instance of the relevant adapter item. If you have a list of Strings that attached with this ListView Adapter you should initialize the String item at the relevant position with the name you want to show. Then call Adapter.notifyDataSetChanged to refresh all UI elements in the ListView with the updated list.

It seems, that you never update the String instance in your Adapter list

You issue is two-fold.

  1. First you are not extracting the updated data from the database (you could assume that the underlying data has been update bit that is risky).
  2. You are not refreshing the Listview with the changes, so it shows the data it knows about.

I'd suggest utilising a CursorAdapter which can simplify matters as Cursor Adapters are designed for use with Cursors and they especially make all data readily available via the adpater as the Cursor is typically positioned at the appropriate row (eg when using onItemClick and onItemLongClick)

The following is an example based upon your code that utilises the SimpleCursorAdapter changing the database and the listview when an item in the list is clicked (to demostrate clicking the same row instead of changing the test to Done it reverses the text so it will will flip for each click).

However, to use a Cursor Adapoter you MUST have a column named _id and that column should be a unique integer (should really be a long rather than int) and typically it would be an alias of the rowid (ie defined using _id INTEGER PRIMARY KEY (with or without AUTOINCREMENT, best without)). As such there is a constant BaseColumns._ID that contains the value _id .

First the DatabaseHelper (subclass of SQLiteOpenHelper) in this case DatabaseHelper.java :-

public class DatabaseHelper extends SQLiteOpenHelper {

    public static final String DBNAME = "mydb";
    public static final  int DBVERSION = 1;

    public static final String TABLE_NAME = "mytable";
    /*<<<<<<<<<< id column must be _id (BaseColumns._ID) for Cursor Adapters >>>>>>>>>*/
    public static final String COLID = BaseColumns._ID;
    public static final String COL1 = "mycol1";
    public static final String COL2 = "mycol2";

    public DatabaseHelper(@Nullable Context context) {
        super(context, DBNAME, null, DBVERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(" +
                COLID + " INTEGER PRIMARY KEY, " +
                COL1 + " TEXT, " +
                COL2 + " TEXT " +
                ")"
        );
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    public long insert(String col1, String col2) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(COL1,col1);
        cv.put(COL2,col2);
        return db.insert(TABLE_NAME,null,cv);
    }

    public int doneName(String finishedName,int id, String oldName) {

        /*
            Alternative using the update convenience method
            Based upon :-
            String query = "UPDATE " + TABLE_NAME + " SET " + COL2 + " = '" + finishedName + "' WHERE " + COL1 +
                " = '" + id + "'" + " AND " + COL2 + " = '" + oldName + "'";

                writes the SQL for you.
                protects against SQL Injection
                returns the number of rows updated
         */
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(COL2,finishedName);
        return db.update(TABLE_NAME,cv,COLID + "=? AND " + COL2 + "=?",new String[]{String.valueOf(id),oldName});
    }

    public Cursor getAll() {
        SQLiteDatabase db = this.getWritableDatabase();
        return db.query(TABLE_NAME,null,null,null,null,null,null);
    }
}
  • Three custom methods insert (inserts a row), getAll (returns a Cursor with all the rows) and your doneName method (rewritten to take advantage the the update convenience method).

  • You may notice the absence of any methods to convert extracted data into a List/ArrayList/Array of objects. This is because there is no need when using a Cursor adapter.

The activity MainActivity.java

public class MainActivity extends AppCompatActivity {

    ListView mListView;
    DatabaseHelper th;
    Cursor csr;
    SimpleCursorAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mListView = this.findViewById(R.id.listview);
        th = new DatabaseHelper(this);
        addSomeTestData();
        manageAdapter();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        csr.close(); //<<<<<<<<<< Should always close Cursors when done with them
    }

    private void manageAdapter() {
        /* This handles but the initialisation and the refreshing of the Listview */
        /* First time it is called it initialises the Adapter and Listview */
        /* On subsequent calls it refreshes the ListView */
        csr = th.getAll();
        if (adapter == null) {
            adapter = new SimpleCursorAdapter(
                    this,
                    android.R.layout.simple_expandable_list_item_2,csr,
                    new String[]{
                            DatabaseHelper.COL1,
                            DatabaseHelper.COL2
                    },
                    new int[]{
                            android.R.id.text1,
                            android.R.id.text2},
                    0
            );
            mListView.setAdapter(adapter);
            mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    if (th.doneName(
                            /* reverses string to test multiple updates of the same row */
                            new StringBuilder(csr.getString(csr.getColumnIndex(DatabaseHelper.COL2))).reverse().toString()
                            /* "Done" */,
                            (int )id /* NOTE ID IS PASSED to onItemClick FOR CURSOR ADAPTER */,
                            csr.getString(csr.getColumnIndex(DatabaseHelper.COL2)) /* NOTE Oldname isn't required as ID will identify the row */
                    ) > 0) {
                        manageAdapter(); //<<<<<<<<< after updating refresh the Cursor and the ListView
                        Toast.makeText(view.getContext(),"Updated OK.",Toast.LENGTH_SHORT).show();
                    } else {
                        Toast.makeText(view.getContext(),"Not Updated!!!",Toast.LENGTH_SHORT).show();
                    }
                }
            });
        } else {
            adapter.swapCursor(csr);
        }
    }

    private void addSomeTestData() {
        //Add some data but only if none exists
        if (DatabaseUtils.queryNumEntries(th.getWritableDatabase(),DatabaseHelper.TABLE_NAME) > 0) return;
        th.insert("TEST1 COL1","TEST1 COL2");
        th.insert("TEST2 COL1","TEST2 COL2");
        th.insert("TEST3 COL1","TEST3 COL2");
        th.insert("TEST4 COL1","TEST4 COL2");
        th.insert("TEST5 COL1","TEST5 COL2");
    }
}
  • Note that you can use your own layouts with SimpleCursorAdapter (4th (String[]) and 5th (int[]) are used to specify the column that the data comes from and the id of the respective view into which the data goes to )

Result:-

When initially run you get:-

在此处输入图像描述

Clicking a row and you get:-

在此处输入图像描述

If you then click all rows you get:-

在此处输入图像描述

And so on.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM