How To Retrieve Multiple Data When Clicked On Listview?
Solution 1:
There are two parts/questions.
First to retrieve the data, so that it can be displayed in the editbills activity, you can utilise the row's id that is passed to the activity in conjunction with the getRecordById
method.
I'd suggest that adding a method to the editbills
class will simplyfy matters.
privatevoidpopulateDisplay(int id) {
Cursorcsr= dbAdapter.getRecordById(id);
if (csr.moveToFirst()) {
editText.setText(csr.getString(csr.getColumnIndex(DBAdapter.KEY_NAME)));
editText2.setText(csr.getString(csr.getColumnIndex(DBAdapter.KEY_AMOUNT)));
editText3.setText(csr.getString(csr.getColumnIndex(DBAdapter.KEY_DUEDATE)));
}
csr.close();
}
You could invoke the above method after retrieving the id from the Intent using :-
populateDisplay(selectedID);
To update based upon the content's of the EditTexts un-comment the updateRecord
method in DBAdapter.java and the change :-
button.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(View view) {
Log.d("test", "adding");
db.open();
longid= db.insertRecord(editText.getText().toString(), editText2.getText().toString(), editText3.getText().toString());
db.close();
Toast.makeText(Editbills.this," Added", Toast.LENGTH_LONG).show();
Intentq=newIntent(getApplicationContext(),bills.class);
startActivity(q);
}
});
to :-
mButton.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(View v) {
if (dbAdapter.updateRecord(
selectedId,
editText.getText().toString(),
editText2.getText().toString(),
editText3.getText().toString())
) {
Log.d("TEST","Row successfully updated.");
Toast.makeText(getApplicationContext(),"Row Updated.",Toast.LENGTH_LONG).show();
populateDisplay(selectedId);
} else {
Toast.makeText(getApplicationContext(),"Row not Updated",Toast.LENGTH_LONG).show();
}
Intentq=newIntent(getApplicationContext(),bills.class);
startActivity(q);
}
});
You will additionally have to add a line initialise the dbAdapter
i.e. dbAdapter = new DBAdapter(this);
i.d suggest adding this line immediately after the line setContentView(R.layout.activity_editbills);
- Note the above code is in-principle and has not been thoroughly tested so it may contains errors.
Edit complete working example :-
The following code is basically an implementation of the above, except modified to utilise a Bill class. Rather than an ArrayList<String>
as the source for the Adapter it has ArrayList<Bill>
.
Thus all the data (id, name, amount and duedate) is available.
You should notice that I've overridden the toString
method to return a String that combines the name, amount and duedate. The ArrayAdapter
uses the object's toString
method to populate the view.
Saying that the critical value is the rowid or an alias of rowid as this can be used to identify a row even if the other data is identical (as would happen when running this example more than once due to the addSomeData
method). Hence, only the id is extracted and passed to the Editbills activity when an item in the list is long clicked (changed from just clicked to reduce the potential for accidental use).
Bill.java
publicclassBill {
private long id;
privateString name;
privateString amount;
privateString duedate;
publicBill(long id, String name, String amount, String duedate) {
this.id = id;
this.name = name;
this.amount = amount;
this.duedate = duedate;
}
/*
Note if this Constructor used then setId should be used
*/publicBill(String name, String amount, String duedate) {
newBill(0,name,amount,duedate);
}
public long getId() {
return id;
}
publicvoidsetId(long id) {
this.id = id;
}
publicStringgetName() {
return name;
}
publicvoidsetName(String name) {
this.name = name;
}
publicStringgetAmount() {
return amount;
}
publicvoidsetAmount(String amount) {
this.amount = amount;
}
publicStringgetDuedate() {
return duedate;
}
publicvoidsetDuedate(String duedate) {
this.duedate = duedate;
}
/*
As ArrayAdapter uses toString method change this
to return all items
*/@OverridepublicStringtoString() {
return name + " " + amount + " " + duedate;
}
}
MainActivity.java
This is the equivalent to your Bills.java without a lot of the bloat such as FAB. :-
publicclassMainActivityextendsAppCompatActivity {
publicstaticfinalStringID_INTENTEXTRA= DBAdapter.KEY_ROWID + "_INTENTEXTRA"; //<<<< ADDED
DBAdapter mDBAdapter;
Cursor mCsr;
ListView mrecycleview;
ArrayAdapter adapter; //<<<< NOT ListAdapter
Context context; // ADDEDprivatestaticfinalStringTAG="assignments";
ArrayList<Bill> mBillList = newArrayList<>();
@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
mrecycleview = this.findViewById(R.id.mRecycleView);
mDBAdapter = newDBAdapter(this);
addSomeData();
adapter = newArrayAdapter<Bill>(
this,
android.R.layout.simple_list_item_1,
mBillList
);
mrecycleview.setAdapter(adapter);
mrecycleview.setOnItemLongClickListener(newAdapterView.OnItemLongClickListener() {
@OverridepublicbooleanonItemLongClick(AdapterView<?> parent, View view, int position, long id) {
Billb= (Bill) adapter.getItem(position);
Intenti=newIntent(context,Editbills.class);
i.putExtra(ID_INTENTEXTRA,b.getId()); //Get ID
startActivity(i);
returntrue;
}
});
rebuildBillList();
}
//<<<< ADDED Method to refresh the ListView resumed@OverrideprotectedvoidonResume() {
super.onResume();
rebuildBillList();
}
// Add some data (note will add 2 rows each time it is run)privatevoidaddSomeData() {
mDBAdapter.insertRecord("Bill1","2018-10-02","English");
mDBAdapter.insertRecord("Bill2","2018-09-03","Mathematics");
mDBAdapter.insertRecord("Bill3","2018-11-04", "Geography");
}
publicvoidrebuildBillList() {
mBillList.clear();
mCsr = mDBAdapter.getAllAsCursor();
while (mCsr.moveToNext()) {
mBillList.add(newBill(
mCsr.getLong(mCsr.getColumnIndex(DBAdapter.KEY_ROWID)),
mCsr.getString(mCsr.getColumnIndex(DBAdapter.KEY_NAME)),
mCsr.getString(mCsr.getColumnIndex(DBAdapter.KEY_AMOUNT)),
mCsr.getString(mCsr.getColumnIndex(DBAdapter.KEY_DUEDATE))
)
);
}
adapter.notifyDataSetChanged();
}
}
- Note the above adds 3 rows each time it is run.
Editbills.java
publicclassEditbillsextendsAppCompatActivity {
Button button;
privatestaticfinalStringTag="assignments";
DBAdapterdb=newDBAdapter(this);
private String selectedName;
privatelong selectedID;
DBAdapter dbAdapter;
private EditText editText,editText2,editText3;
Context context;
@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_editbills);
context = this;
dbAdapter = newDBAdapter(this); //<<<< ADDED
button=(Button)findViewById(R.id.button);
editText =(EditText)findViewById(R.id.edittext);
editText2=(EditText)findViewById(R.id.edittext2);
editText3 =(EditText)findViewById(R.id.edittext3);
//get the intent extra from the ListDataActivityIntentreceivedIntent= getIntent();
//now get the itemID we passed as an extra
selectedID = receivedIntent.getLongExtra(MainActivity.ID_INTENTEXTRA,-1L); //NOTE: -1 is just the default value
populateDisplay(selectedID);
//now get the name we passed as an extra//selectedName = receivedIntent.getStringExtra("name");//set the text to show the current selected name//editText.setText(selectedName); <<<< commented out
button.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(View view) {
/*
Log.d("test", "adding");
db.open();
long id = db.insertRecord(editText.getText().toString(), editText2.getText().toString(), editText3.getText().toString());
db.close();
Toast.makeText(Editbills.this," Added", Toast.LENGTH_LONG).show();
*//*
* <<<< Not the way as it ends/closes the existing activity
Intent q = new Intent(getApplicationContext(),MainActivity.class);
startActivity(q);
*/Stringtoast="Updated.";
if (dbAdapter.updateRecord(selectedID,
editText.getText().toString(),
editText2.getText().toString(),
editText3.getText().toString())) {
} else {
toast = "Not Updated.";
}
Toast.makeText(context,toast,Toast.LENGTH_LONG).show();
finish(); //<<<< ends/closes this activity and returns to calling activity
}
});
}
privatevoidpopulateDisplay(long id) {
Cursorcsr= dbAdapter.getRecordById(id);
if (csr.moveToFirst()) {
editText.setText(csr.getString(csr.getColumnIndex(DBAdapter.KEY_NAME)));
editText2.setText(csr.getString(csr.getColumnIndex(DBAdapter.KEY_AMOUNT)));
editText3.setText(csr.getString(csr.getColumnIndex(DBAdapter.KEY_DUEDATE)));
}
csr.close();
}
}
- Basically as per the original answer.
DBAdapter.java
publicclassDBAdapter {
publicstaticfinalStringKEY_ROWID="id";
publicstaticfinalStringKEY_NAME="name";
publicstaticfinalStringKEY_AMOUNT="amount";
publicstaticfinalStringKEY_DUEDATE="duedate";
privatestaticfinalStringTAG="DBAdapter";
privatestaticfinalStringDATABASE_NAME="billsdb";
privatestaticfinalStringDATABASE_TABLE="bills";
privatestaticfinalintDATABASE_VERSION=2;
// Replaces DATABASE_CREATE using the one source definitionprivatestaticfinalStringTABLE_CREATE="CREATE TABLE IF NOT EXISTS " + DATABASE_TABLE + "(" +
KEY_ROWID + " INTEGER PRIMARY KEY, " + // AUTOINCREMENT NOT REQD
KEY_NAME + " DATE NOT NULL, " +
KEY_AMOUNT + " VARCHAR ," +
KEY_DUEDATE + " DATE " +
")";
private Context context;
private DatabaseHelper DBHelper;
private SQLiteDatabase db;
publicDBAdapter(Context ctx)
{
this.context = ctx;
DBHelper = newDatabaseHelper(context);
}
privatestaticclassDatabaseHelperextendsSQLiteOpenHelper
{
DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@OverridepublicvoidonCreate(SQLiteDatabase db)
{
db.execSQL(TABLE_CREATE); // NO need to encapsulate in try clause
}
@OverridepublicvoidonUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS contacts"); //????????
db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
onCreate(db);
}
}
//---opens the database--- NOT NEEDEDpublic DBAdapter open()throws SQLException
{
db = DBHelper.getWritableDatabase();
returnthis;
}
//---closes the database--- NOT NEEDEDpublicvoidclose()
{
DBHelper.close();
}
//---insert a record into the database---publiclonginsertRecord(String name, String amount, String duedate)
{
ContentValuesinitialValues=newContentValues();
initialValues.put(KEY_NAME, name);
initialValues.put(KEY_AMOUNT, amount);
initialValues.put(KEY_DUEDATE, duedate);
return DBHelper.getWritableDatabase().insert(DATABASE_TABLE,
null,
initialValues
);
}
//---deletes a particular record---publicbooleandeleteContact(long rowId)
{
return db.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
}
//---retrieves all the records--- SEE FOLLOWING METHODpublic Cursor getAllRecords()
{SQLiteDatabasedb= DBHelper.getWritableDatabase();
Stringquery="SELECT * FROM " + DATABASE_TABLE;
Cursordata= db.rawQuery(query,null);
return data;
}
//As per getAllRecords but using query convenience methodpublic Cursor getAllAsCursor() {
return DBHelper.getWritableDatabase().query(
DATABASE_TABLE,
null,null,null,null,null,null
);
}
public Cursor getItemID(String name) {
SQLiteDatabasedb= DBHelper.getWritableDatabase();
Stringquery="SELECT " + KEY_ROWID + " FROM " + DATABASE_TABLE +
" WHERE " + KEY_NAME + " = '" + name + "'";
Cursordata= db.rawQuery(query, null);
return data;
}
// Retrieve a row (single) according to idpublic Cursor getRecordById(long id) {
return DBHelper.getWritableDatabase().query(
DATABASE_TABLE,
null,
KEY_ROWID + "=?",
newString[]{String.valueOf(id)},
null,null,null
);
}
//---updates a record---publicbooleanupdateRecord(long rowId, String name, String amount, String duedate) {
ContentValuesargs=newContentValues();
args.put(KEY_NAME, name);
args.put(KEY_AMOUNT, amount);
args.put(KEY_DUEDATE, duedate);
Stringwhereclause= KEY_ROWID + "=?";
String[] whereargs = newString[]{String.valueOf(rowId)};
return DBHelper.getWritableDatabase().update(DATABASE_TABLE,
args,
whereclause,
whereargs
) > 0;
}
}
- Basically as was except that
upDateRecord
has been un-commented, again as per the original answer.
Results
1st Run - MainActivity (Bills) :-
Long Click Bill2 (note changed from Click as Long Click is less prone to accidental use)
Change data (Update button not clicked)
Update Button Clicked (Toast was Updated.)
- Note use of
finish()
to return to the invoking activity and then the use ofonResume
to refresh the list according to the updated data (possibly your next question).- using
startActivity
will simply result in issues.
- using
- Note Values are date and course rather then amount and duedate because I didn't change the values in the
addSomeData
method (easily done).- the actual data itself is irrelevant to the process.
Post a Comment for "How To Retrieve Multiple Data When Clicked On Listview?"