I have have checked every problem here in relation to my own. The codes are totally different in the one I'm using IMHO. I have coded everything up to this point. I've read that in deleting the data in the database is just by passing the position, the problem is the auto-generated id in the database is not the same with the position being passed. All I'm trying to achieve is after deleting the item in list view, the item in the database will also be deleted.
The code from database in getting all the data:
public ArrayList<String> getData() {
String[] columns = new String[] { KEY_ID, KEY_CLIENT_NAME,
KEY_PRODUCT_NAME, KEY_SUPPLIER_PRICE, KEY_BS_PRICE, KEY_QTY,
KEY_TOTAL_AMOUNT };
Cursor c = sql.query(DB_TABLE, columns, null, null, null, null, null);
ArrayList<String> result = new ArrayList<String>();
int id = c.getColumnIndex(KEY_ID);
int cName = c.getColumnIndex(KEY_CLIENT_NAME);
int pName = c.getColumnIndex(KEY_PRODUCT_NAME);
int suppPrice = c.getColumnIndex(KEY_SUPPLIER_PRICE);
int bsPrice = c.getColumnIndex(KEY_BS_PRICE);
int qty = c.getColumnIndex(KEY_QTY);
int totalAmount = c.getColumnIndex(KEY_TOTAL_AMOUNT);
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
result.add("ID: " + c.getInt(id) + "\n" + "CLIENT NAME: "
+ c.getString(cName) + "\n" + "PRODUCT NAME: "
+ c.getString(pName) + "\n" + "SUPPLIER PRICE: "
+ c.getString(suppPrice) + "\n" + "RETAIL PRICE: "
+ c.getString(bsPrice) + "\n" + "QUANTITIY: "
+ c.getString(qty) + "\n" + "TOTAL: "
+ c.getString(totalAmount) + "\n");
}
return result;
}
The code in retrieving the data:
sql = new SQLDatabase(this);
sql.open();
ArrayList<String> data = sql.getData();
sql.close();
The code the the deletion should be executed:
protected void onListItemClick(View view, int position, long id) {
Log.i("TAG", "onListItemClick id=" + position + id);
AlertDialog.Builder builder = new AlertDialog.Builder( Delete.this);
builder.setMessage("WHAT DO YOU WANT TO DO?");
builder.setNegativeButton("DELETE", new
DialogInterface.OnClickListener() {
#Override public void onClick(DialogInterface dialog, int which) { }
// DELETE CODE HERE
});
builder.setNeutralButton("CANCEL", new
DialogInterface.OnClickListener() {
#Override public void onClick(DialogInterface dialog, int which) { }
// DO NOTHING
});
builder.setCancelable(false); AlertDialog alertdialog =
builder.create(); alertdialog.show();
}
Add Tag to the column you inserted and use same tag value while delete operation in both list and DB.
Related
I have a ListView and i have put an onClickListener to it. When i click it, it is supposed to run an AlertDialog but it does not seem to work. The AlertDialog is supposed to display a few strings which are in the ListView. here is the code I am using.
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
PopUpAlert(id);
}
});
private void PopUpAlert(final long id) {
Cursor cursor = dbHelper.getAllReviewRows(id);
if (cursor.moveToFirst()) {
//Preparing variables to use in message from Establishment record in Database
final String SName = cursor.getString(dbHelper.COL_REV_STATION_NAME);
String Date = cursor.getString(SQL.COL_DATE);
String SFacility = cursor.getString(SQL.COL_REV_FACILITY);
String Rating = cursor.getString(SQL.COL_RATING);
String Comment = cursor.getString(SQL.COL_COMMENTS);
// building a drill down information message and displaying it in an Alert Dialog
new AlertDialog.Builder(this)
.setTitle("Facilities Review App")
.setMessage("You Selected:\n"
+ "Station Name: " + SName + "\n" + "Date: " + Date
+ "\n" + "Facility: " + SFacility + "\n" + "Rating: " + Rating
+ "\n" + "Comment: " + Comment)
.setPositiveButton("Add Image", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// calling method to add a review for that particular establishment
addImage(SName);
}
})
.setNegativeButton("Delete", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// calling method to delete that particular establishment
}
});
}
}
you didn't call show() on your AlertDialog:
new AlertDialog.Builder(this)
.setTitle("Facilities Review App")
.setMessage("...")
.setPositiveButton(..)
.setNegativeButton(..)
.show();
Here you can find the documentation for AlertDialog.Builder.show()
The app i'm making displays user input before saving it. One of the spinners gets data from a database. When i press the "review" button my app crashes (something about a NullPointException) on this line
final String estStatus = estType[row];
Here is the code.
private void displayReviewDetails() {
// Get what the user entered
Spinner estSpinner = (Spinner) findViewById (R.id.est_spinner);
Spinner spinner = (Spinner) findViewById (R.id.ratingSpinner);
EditText mealCost = (EditText) findViewById (R.id.editTextMealCost);
EditText mealType = (EditText) findViewById (R.id.editTextMealType);
EditText comments = (EditText) findViewById (R.id.editTextComments);
DatePicker rDate = (DatePicker) findViewById (R.id.datePicker1);
// final so we can reference them in the anonymous inner class below
int row = estSpinner.getSelectedItemPosition();
final String estStatus = estType[row];
int row1 = spinner.getSelectedItemPosition();
final String ratingStatus = estRating[row1];
final String strMealCost = mealCost.getText().toString();
final String strMealType = mealType.getText().toString();
final String strComments = comments.getText().toString();
final String rateDate = rDate.getDayOfMonth() + "/"
+ (rDate.getMonth() + 1) + "/" + rDate.getYear();
// Create and display the Alert dialog
new AlertDialog.Builder(this)
.setTitle("Details entered")
.setMessage(
"\n " + estStatus +
"\n " + ratingStatus +
"\n " + strMealCost +
"\n " + strMealType +
"\n " + strComments +
"\n " + rateDate )
.setNeutralButton("Back",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do nothing - it will just close when clicked
}
})
.setPositiveButton("Save",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// save the details entered if "Save" button clicked
saveReviews(estStatus, ratingStatus, strMealCost, strMealType,
strComments, rateDate);
}
}).show();
You can also use getSelectedItem().toString();
I am attempting to delete a record from my database,
Short Summary:
My database populates a listview
The user can click the listview and
view more details on a new activity
I want to able to delete the
record from this new activity
CODE
I have a class named ModuleDatabaseHandler that manages the database. In this, I have a method called getData() that populates records to a ListView in ActivityViewAll:
ModuleDatabaseHandler
public ArrayList<String> getData() {
// TODO Auto-generated method stub
String[] columns = new String[] { KEY_ROWID, KEY_MODULE_CODE,
KEY_MODULE_NAME, KEY_LECTURE_PRACTICAL,
KEY_LECTURE_PRACTICAL_SHORT, KEY_LECTURE_DAY,
KEY_LECTURE_DAY_SHORT, KEY_START_TIME, KEY_END_TIME,
KEY_LOCATION, ADDITIONAL_INFO };
Cursor c = ourDatabase.query(DATABASE_MODULES, columns, null, null,
null, null, null);
ArrayList<String> results = new ArrayList<String>();
int indexModCode = c.getColumnIndex(KEY_MODULE_CODE);
int indexLectPracShort = c.getColumnIndex(KEY_LECTURE_PRACTICAL_SHORT);
int indexLectDayShort = c.getColumnIndex(KEY_LECTURE_DAY_SHORT);
int indexLectStart = c.getColumnIndex(KEY_START_TIME);
int indexLectLoc = c.getColumnIndex(KEY_LOCATION);
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
results.add(c.getString(indexModCode) + " "
+ c.getString(indexLectPracShort) + " "
+ c.getString(indexLectDayShort) + " "
+ c.getString(indexLectStart) + " "
+ c.getString(indexLectLoc));
}
return results;
}
This data is read in by ActivityViewAll:
ActivityViewAll
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_modules_test);
ModuleDatabaseHandler info = new ModuleDatabaseHandler(this);
info.open();
ArrayList<String> data = info.getData();
info.close();
l = (ListView) findViewById(R.id.listView1);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, data);
l.setAdapter(adapter);
l.setOnItemClickListener(this);
}
I have another method in the ModuleDatabaseHandler class called getAllData() that allows the user to press a ListView item and read full details about the item on a new activity, ActivityFullDetails:
public String getAllData(int specified_position) {
// TODO Auto-generated method stub
int position = specified_position;
if(c.moveToPosition(specified_position)) {
String result = "";
for(int columnIndex = 0; columnIndex<c.getColumnCount();columnIndex++) {
result += c.getString(columnIndex)+" ";
}
return result;
} else {
throw new IllegalArgumentException("Row " + specified_position + " does not exist");
}
}
The data is transfered from the listView in ActivityViewAll to ActivityFullDetails using onItemClick:
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
TextView temp = (TextView) view;
Toast.makeText(this, temp.getText() + " " + i, Toast.LENGTH_SHORT)
.show();
ModuleDatabaseHandler info = new ModuleDatabaseHandler(this);
info.open();
String module_info = info.getAllData(i);
info.close();
Intent fullModuleDetails = new Intent();
fullModuleDetails.setClassName("com.example.collegetimetable",
"com.example.collegetimetable.ModuleDetails");
fullModuleDetails.putExtra("list1", module_info);
startActivity(fullModuleDetails);
}
Back in the ModuleDatabaseHandler class, I created a method called deleteEntry to attempt to delete a row:
public void deleteEntry(long row){
ourDatabase.delete(DATABASE_MODULES, KEY_ROWID + "=" + row, null);
}
The Problem
How can I pass the ROW_ID from the ModuleDatabaseHandler class to the listView in ActivityViewAll and then to the ActivityFullDetails so I can delete the record?
SOLVED
Thanks to Serge who helped me solve this, by creating a getRowId method as seen in the accepted answer. Although I did have to add a cursor query within the method which is not shown in the accepted answer i.e.:
public int getRowID(int specified_position) {
String[] columns = new String[]{ KEY_ROWID, KEY_MODULE_CODE, KEY_MODULE_NAME, KEY_LECTURE_PRACTICAL, KEY_LECTURE_DAY, KEY_START_TIME,KEY_END_TIME, KEY_LOCATION, ADDITIONAL_INFO};
Cursor c = ourDatabase.query(DATABASE_MODULES, columns, null, null, null, null, null);
// rest of method as shown below
}
This method is called in the ActivityViewAll activity page from an instance of ModuleDatabaseHandler class, passed to the ActivityFullDetails page using putExtra,(and received using getIntent().getExtras as usual)..the delete method can then use the rowid.
Add function
public int getRowID(int specified_position) {
int position = specified_position;
if(c.moveToPosition(specified_position)) {
return c.getInteger(c.getColumnIndex(KEY_ROWID));
} else {
throw new IllegalArgumentException("Row " + specified_position + " does not exist");
}
}
And then to get it use
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
TextView temp = (TextView) view;
Toast.makeText(this, temp.getText() + " " + i, Toast.LENGTH_SHORT)
.show();
ModuleDatabaseHandler info = new ModuleDatabaseHandler(this);
info.open();
String module_info = info.getAllData(i);
int rowID = info.getRowID(i);
info.close();
Intent fullModuleDetails = new Intent();
fullModuleDetails.setClassName("com.example.collegetimetable",
"com.example.collegetimetable.ModuleDetails");
fullModuleDetails.putExtra("list1", module_info);
fullModuleDetails.putExtra("rowid", rowID);
startActivity(fullModuleDetails);
}
I have a method named getData that populates a listView from my database limited to specified columns from the table:
public ArrayList<String> getData() {
// TODO Auto-generated method stub
String[] columns = new String[] { KEY_ROWID, KEY_MODULE_CODE,
KEY_MODULE_NAME, KEY_LECTURE_PRACTICAL,
KEY_LECTURE_PRACTICAL_SHORT, KEY_LECTURE_DAY,
KEY_LECTURE_DAY_SHORT, KEY_START_TIME, KEY_END_TIME,
KEY_LOCATION, ADDITIONAL_INFO };
Cursor c = ourDatabase.query(DATABASE_MODULES, columns, null, null,
null, null, null);
ArrayList<String> results = new ArrayList<String>();
int indexModCode = c.getColumnIndex(KEY_MODULE_CODE);
int indexLectPracShort = c.getColumnIndex(KEY_LECTURE_PRACTICAL_SHORT);
int indexLectDayShort = c.getColumnIndex(KEY_LECTURE_DAY_SHORT);
int indexLectStart = c.getColumnIndex(KEY_START_TIME);
int indexLectLoc = c.getColumnIndex(KEY_LOCATION);
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
results.add(c.getString(indexModCode) + " "
+ c.getString(indexLectPracShort) + " "
+ c.getString(indexLectDayShort) + " "
+ c.getString(indexLectStart) + " "
+ c.getString(indexLectLoc));
}
return results;
}
This works fine and here is how I populate my listview (ModuleDatabaseHandler is the class where the database is managed):
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_modules_test);
ModuleDatabaseHandler info = new ModuleDatabaseHandler(this);
info.open();
ArrayList<String> data = info.getData();
info.close();
l = (ListView) findViewById(R.id.listView1);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1 ,data);
l.setAdapter(adapter);
l.setOnItemClickListener(this);
}
I want to be able to click the listView item, and view ALL the information pertaining to the record (in the listView it only shows certain information). I have attempted to create a new method in the ModuleDatabaseHandler class called getAllData.
Below is the OnItemClick for the ListView item which launches a new activity, passing through the information from getAllData using putExtra:
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
TextView temp = (TextView) view;
Toast.makeText(this, temp.getText() + " " + i, Toast.LENGTH_SHORT)
.show();
ModuleDatabaseHandler info = new ModuleDatabaseHandler(this);
info.open();
String module_info = info.getAllData(); // METHOD TO GET ALL DATA
info.close();
Intent fullModuleDetails = new Intent();
fullModuleDetails.setClassName("com.example.collegetimetable",
"com.example.collegetimetable.ModuleDetails");
fullModuleDetails.putExtra("list1", module_info);
startActivity(fullModuleDetails);
}
Here is the getAllData method which retrieves all the information from the database. How could I alter this method, to retrieve only the information for the row relating to the particular listView item that was clicked by the user?
public String getAllData() {
String[] columns = new String[]{ KEY_ROWID, KEY_MODULE_CODE, KEY_MODULE_NAME, KEY_LECTURE_PRACTICAL, KEY_LECTURE_DAY, KEY_START_TIME,KEY_END_TIME, KEY_LOCATION, ADDITIONAL_INFO};
Cursor c = ourDatabase.query(DATABASE_MODULES, columns, null, null, null, null, null);
String results = "";
int indexRow = c.getColumnIndex(KEY_ROWID);
int indexModCode = c.getColumnIndex(KEY_MODULE_CODE);
int indexModName = c.getColumnIndex(KEY_MODULE_NAME);
int indexLectPrac = c.getColumnIndex(KEY_LECTURE_PRACTICAL);
int indexLectDay = c.getColumnIndex(KEY_LECTURE_DAY);
int indexLectStart = c.getColumnIndex(KEY_START_TIME);
int indexLectEnd = c.getColumnIndex(KEY_END_TIME);
int indexLectLoc = c.getColumnIndex(KEY_LOCATION);
int indexLectInfo = c.getColumnIndex(ADDITIONAL_INFO);
for (c.moveToFirst();!c.isAfterLast();c.moveToNext()){
results = results + ( c.getString(indexModCode) + " " + c.getString(indexModName) + " " + c.getString(indexLectPrac)
+ " " + c.getString(indexLectDay) + " " + c.getString(indexLectStart) + " " + c.getString(indexLectEnd) + " "
+ c.getString(indexLectLoc) + " " + c.getString(indexLectInfo));
}
return results;
}
Thanks for any help
Instead of looping through the data, you would do something along the lines:
public String getAllDataForRow(int row) {
String[] columns = new String[]{ KEY_ROWID, KEY_MODULE_CODE, KEY_MODULE_NAME, KEY_LECTURE_PRACTICAL, KEY_LECTURE_DAY, KEY_START_TIME,KEY_END_TIME, KEY_LOCATION, ADDITIONAL_INFO};
Cursor c = ourDatabase.query(DATABASE_MODULES, columns, null, null, null, null, null);
if(c.moveToPosition(row)) {
String result = "";
for(int columnIndex = 0; columnIndex<c.getColumnCount();columnIndex++) {
result += c.getString(columnIndex)+" ";
}
return result;
} else {
throw new IllegalArgumentException("Row " + row + " does not exist");
}
}
Also, if you didn't know: If you want all columns, you actually do not have to specify them in the projection, but can just pass null instead of columns.
Hope that helps.
I have a simple ListActivity that uses the SimpleCursorAdapter. I allow users to change one of the values using an EditText. I perform simple validation to make sure that the number entered is less than 100. If the user entered value fails validation, I want to put the old value back.
I've tried a few different ways. My current approach is to requery it out of the database, but this isn't working. I'm always getting the value associated with the last entry in the ListActivity, regardless of which one was actually changed. I noticed in LogCat that onTextChanged and afterTextChanged are firing multiple times for each row in the ListActivity and not just the one that changed.
Here's the code:
public class MySimpleCursorAdapter extends SimpleCursorAdapter {
Context lcontext;
boolean changed;
String lastval;
private PortfolioData pfdata;
public MySimpleCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);
lcontext = context;
}
#Override
public View getView(final int pos, View v, ViewGroup parent) {
v = super.getView(pos, v, parent);
final EditText et = (EditText) v.findViewById(R.id.classpercentage);
final TextView tv = (TextView) v.findViewById(R.id._id);
et.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
Log.d("TEST", "In afterTextChanged s=" + s.toString() + " "
+ tv.getText() + " POS = " + Integer.toString(pos));
lastval = tv.getText().toString();
if (changed == true) {
String enteredValue = s.toString();
if (checkNullValues(enteredValue)) {
if (Float.parseFloat(enteredValue.trim()) > 100.0f) {
AlertDialog.Builder builder = new AlertDialog.Builder(
lcontext);
builder.setMessage("Percentage Value should be Less than 100");
builder.setPositiveButton("Ok",
new DialogInterface.OnClickListener() {
public void onClick(
DialogInterface arg0, int arg1) {
String sql = "select c.percentage as PERCENTAGE " +
"from asset_classes c WHERE c._id = " + lastval + ";";
pfdata = new PortfolioData(lcontext);
SQLiteDatabase db = pfdata.getReadableDatabase();
Cursor cursor = db.rawQuery(sql, null);
if (cursor != null)
{
cursor.moveToFirst();
et.setText(cursor.getString(0));
}
cursor.close();
pfdata.close();
}
});
// End of the Alert
if (changed == true)
{
builder.show();
}
}
}
changed = false;
}
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// Log.d("TEST", "In beforeTextChanged start=" +
// Integer.toString(start) +" count="+ Integer.toString(count) +
// " after=" + Integer.toString(after) + " s=" + s + " " + tv);
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
Log.d("TEST", "In onTextChanged start=" +
Integer.toString(start) + " count=" + Integer.toString(count)
+ " before=" + Integer.toString(before) + " s=" + s + " " +
tv);
changed = true;
}
});
return v;
}
}
I would really appreciate a fresh perspective on this. As always, thanks in advance.
Try to use an onFocusChangeListener. When it gets focus, save the current text into field of the class.
Something like:
String oldText - Would be your old text field.
Then you do:
et.setOnFocusChangeListener(new OnFocusChangeListener()) {
#Override
public void onFocusChange(View whatever, boolean hasFocus) {
if (hasFocus) {
//code
} else {
//code or maybe empty
}
}
}
Then if the number is > 100 you just get the oldText value and put in the EditText.
I think you're not aware of recycling in ListView. Having 1000 rows in Cursor there is only 10-20 (depends on screen size) row views created.
Don't store data in view!
At beggining I recommend you to read http://commonsware.com/Android/excerpt.pdf