Checkbox losing state on scroll using cursorAdapter - android

I'm currently working on a simple Android application which will allow a user to add/remove/delete a record from a sqlite DB using checkboxes.
The main activity has a listview which renders objects from an exercise adapter. The adapter extends from cursor adapter.
The issue I'm having is when selecting a checkbox, then scrolling down the list so that the checkbox is out of view, the state is lost.
Here are extracts of my main activity and my exercise adapter:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbManager = new DBManager(this);
dbManager.open();
adapter = new ExerciseAdapter(this, dbManager.fetch());
listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(adapter);
}
public void deleteExercise(View view) {
for (int i = 0; i < adapter.getCount(); i++) {
CheckBox c = listView.getChildAt(i).findViewById(R.id.checkBox);
if (c.isChecked()) {
deleteIds.add(adapter.getItemId(i));
}
}
for (Long deleteId : deleteIds) {
dbManager.delete(deleteId);
adapter.update(dbManager.fetch());
}
}
ExerciseAdapter:
public class ExerciseAdapter extends CursorAdapter {
public ExerciseAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.exercise, parent, false);}
#Override
public void bindView(View view, Context context, Cursor cursor) {
// Find fields to populate in inflated template
TextView exerciseTitle = view.findViewById(R.id.exerciseTitle);
TextView exerciseDesc = view.findViewById(R.id.exerciseDescription);
TextView exerciseDate = view.findViewById(R.id.exerciseDate);
// Extract properties from cursor
String title = cursor.getString(cursor.getColumnIndexOrThrow("title"));
String desc = cursor.getString(cursor.getColumnIndexOrThrow("description"));
String date = cursor.getString(cursor.getColumnIndexOrThrow("date"));
// Populate fields with extracted properties
exerciseTitle.setText(title);
exerciseDesc.setText(String.valueOf(desc));
exerciseDate.setText(String.valueOf(date));
}
public void update(Cursor cursor) {
this.swapCursor(cursor);
this.notifyDataSetChanged();
}
}
This is adopted code so would like to keep the classes similar to how they are now, unless there is no other option and a big change is required.
Thanks.

Related

How do I change custom CursorAdapter to display only specific rows in the listview for a given fragment?

Three fragments in my app, Fragment1, Fragment2, Fragment3 display contents of a single table in a listview, using a single custom CursorAdapter class, TaskCursorAdapter. Here is the class:
public class TaskCursorAdapter extends CursorAdapter {
public TaskCursorAdapter(Context context, Cursor c) {
super(context, c, 0 /* flags */);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.list_item_task, parent, false);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
TextView titleTextView = (TextView) view.findViewById(R.id.task_title);
TextView detailsTextView = (TextView) view.findViewById(R.id.task_details);
int titleColumnIndex = cursor.getColumnIndex(TaskEntry.COLUMN_TASK_TITLE);
int detailsColumnIndex = cursor.getColumnIndex(TaskEntry.COLUMN_TASK_DETAILS);
String taskTitle = cursor.getString(titleColumnIndex);
String taskDetails = cursor.getString(detailsColumnIndex);
if (TextUtils.isEmpty(taskDetails)) {
taskDetails = context.getString(R.string.unknown_task);
}
titleTextView.setText(taskTitle);
detailsTextView.setText(taskDetails);
}
}
The table is specified in the Contract class as TaskEntry. It also has another column named TaskEntry.COLUMN_TASK_STATUS="status". The possible values are 0, 1 or 2. Currently, all the items are displayed in both fragments. But, I want to make it so that only the rows with status=0 are displayed in Fragment1, those with status=1 in Fragment2 and those with status=2 in Fragment3.
I tried the following in bindView method:
int taskStatus = Integer.parseInt(cursor.getString(cursor.getColumnIndex(TaskEntry.COLUMN_TASK_STATUS)));
if(taskStatus==0) { //code in bindView }
This resulted in displaying only the items with status=0 in all fragments, but it left an empty inflated view in place of the item with status other than 0.
Also, I cannot find a way to pass the information to make it specific to Fragment1.
How should I conditionally display rows based on status value and fragment?
EDIT:
What worked:
Instead of trying this in TaskCursorAdapter, I used conditional query in onCreateLoader method like the following in each fragment:
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String selectionArgs[] = {"<status>"};
String[] projection = {
TaskEntry._ID,
TaskEntry.COLUMN_TASK_TITLE,
TaskEntry.COLUMN_TASK_DETAILS};
return new CursorLoader(this.getActivity(), TaskEntry.CONTENT_URI, projection,
TaskEntry.COLUMN_TASK_STATUS + " = ?", selectionArgs, null);
}
Try this:
public class TaskCursorAdapter extends CursorAdapter {
private int statusCode;
public TaskCursorAdapter(Context context, Cursor c) {
super(context, c, 0 /* flags */);
}
public setStatusCode(int statusCode){
this.statusCode = statusCode;
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
int currentStatusCode = Integer.parseInt(cursor.getString(cursor.getColumnIndex(TaskEntry.COLUMN_TASK_STATUS)));
if(statusCode == currentStatusCode){
return LayoutInflater.from(context).inflate(R.layout.list_item_task, parent, false);
} else return null;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
if(view != null){
TextView titleTextView = (TextView) view.findViewById(R.id.task_title);
TextView detailsTextView = (TextView) view.findViewById(R.id.task_details);
int titleColumnIndex = cursor.getColumnIndex(TaskEntry.COLUMN_TASK_TITLE);
int detailsColumnIndex = cursor.getColumnIndex(TaskEntry.COLUMN_TASK_DETAILS);
String taskTitle = cursor.getString(titleColumnIndex);
String taskDetails = cursor.getString(detailsColumnIndex);
if (TextUtils.isEmpty(taskDetails)) {
taskDetails = context.getString(R.string.unknown_task);
}
titleTextView.setText(taskTitle);
detailsTextView.setText(taskDetails);
}
}
}
and do this in each of your fragments, passing in your status codes, respectively:
yourAdapter = new TaskCursorAdapter(this, yourDataCursor);
yourAdapter.setStatusCode(YOUR_STATUS_CODE);
yourListView.setAdapter(yourAdapter);
EDIT (It turns out we can't return null from CursorAdapter#newView()
So I guess you are going to have to filter your cursor in each Fragment before instantiating a new TaskCursorAdapter, and pass in your filtered cursor instead of your original cursor. You can use CursorWrapper class for that. This answer might give you an idea: https://stackoverflow.com/a/7343721/8354184.

Deleting a row from a ListView using Button associated with it

I have a listview on which i am showing data from my database and now i want to delete row on the basis of button clicked which is associated with each row.
i am having exception in CustomAdapter class whenever i press Done button.
CursorAdapter code is this:
public class CustomAdapter extends CursorAdapter {
TextView task,daate;
Button del;
public static int id;
Context ct;
public CustomAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
}
// The newView method is used to inflate a new view and return it,
// you don't bind any data to the view at this point.
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
ct=context;
return LayoutInflater.from(context).inflate(R.layout.adapter, parent, false);
}
// The bindView method is used to bind all data to a given view
// such as setting the text on a TextView.
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final DatabaseHelper help=new DatabaseHelper(ct);
del = (Button) convertView.findViewById(R.id.deleteBtn);
del.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View v) {
help.deleteRecordWithId(position);
}
}
);
return super.getView(position, convertView, parent);
}
#Override
public void bindView(View view, Context context, final Cursor cursor) {
// Find fields to populate in inflated template
task = (TextView) view.findViewById(R.id.dynamicTask);
daate = (TextView) view.findViewById(R.id.dynamicDate);
id=cursor.getInt(cursor.getColumnIndex("_id"));
String Task=cursor.getString(cursor.getColumnIndex("task"));
String Daate=cursor.getString(cursor.getColumnIndex("ddate"));
task.setText(Task);
daate.setText(Daate);
}
}
and my database function deleteRecordWithId() is:
public boolean deleteRecordWithId(int id) {
SQLiteDatabase db=this.getWritableDatabase();
long rows=db.delete(TABLE_NAME,"_id=?",new String[] {String.valueOf(id)});
if(rows>0) {
return true;
}
else {
return false;
}
}
and i am getting this exception:
java.lang.NullPointerException: Attempt to invoke virtual method
'android.view.View android.view.View.findViewById(int)' on a null object
reference
What is wrong in this code. please help me to rectify it.
Replace this:
help.deleteRecordWithId(position);
with:
CustomAdapter.this.remove(CustomAdapter.this.getItem(position));
CustomAdapter.this.notifyDataSetChanged();
It will delete data from your adapter and notifydatasetchanged will update your listview accordingly.
First Method: You describe like that
public class CustomAdapter extends CursorAdapter {
TextView task,daate;
Button del;
public static int id;
Context ct;
public CustomAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
ct=context;
return LayoutInflater.from(context).inflate(R.layout.adapter, parent, false);
}
#Override
public void bindView(View view, Context context, final Cursor cursor) {
// Find fields to populate in inflated template
task = (TextView) view.findViewById(R.id.dynamicTask);
daate = (TextView) view.findViewById(R.id.dynamicDate);
id=cursor.getInt(cursor.getColumnIndex("_id"));
String Task=cursor.getString(cursor.getColumnIndex("task"));
String Daate=cursor.getString(cursor.getColumnIndex("ddate"));
task.setText(Task);
daate.setText(Daate);
final DatabaseHelper help=new DatabaseHelper(ct);
del = (Button) convertView.findViewById(R.id.deleteBtn);
}}
MainActivity:
public class MainActivity{
private CustomAdapter cursorAdapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
cursorAdapter = new CustomAdapter(this, null);
}
public void deleteRecordWithId(View view) {
View parentRow = (View) view.getParent().getParent();
ListView listView = (ListView) view.getParent().getParent().getParent();
int position = listView.getPositionForView(parentRow);
long id = cursorAdapter.getItemId(position);
SQLiteDatabase db=this.getWritableDatabase();
long rows=db.delete(TABLE_NAME,"_id=?",new String[] {String.valueOf(id)});
if(rows>0) {
return true;
}
else {
return false;
}
}
}
and xml like that:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/task_outer_container"
android:layout_width="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:gravity="center_vertical"
android:background="#drawable/background_transparent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:clipChildren="false"
>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:id="#+id/delete_button"
android:onClick="deleteRecordWithId"
app:srcCompat="#drawable/remove_icon"
android:background="#drawable/background_transparent"
android:layout_gravity="center_vertical"
android:adjustViewBounds="false"
android:paddingStart="7dp"
android:paddingEnd="7dp"
android:layout_marginEnd="-5dp"/>
</RelativeLayout>
Second Method: You should not use getView in the Cursoradapter. You need to do all the operations in bindview. So uou can not reach id with getview.
For example: https://github.com/rodoggx/w4d1_Simple_CursorAdapter/blob/master/app/src/main/java/com/example/sqlitecursoradapter/CustomAdapter.java
set setOnItemClickListener to your listview...
yourListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
yourListView.remove(position);
database.removeItem(id);//create removemethod in database class
}
});
Define removeItem method
public void remove(long id){
String str =String.valueOf(id);
database.execSQL("DELETE FROM <TABLE_NAME> WHERE _id = '" + str + "'");
}
ListView doesn't give a straightforward way to implement actions to views inside an item. Use RecyclerView instead, it's more customizable and good for performance than the list view.
Create Lists and Cards - Android Developer

CursorAdapter changed style of SwipeMenuListView after scroll

I'm trying to develop an app to record debts in which I have a SwipeMenuListView from this github https://github.com/baoyongzhang/SwipeMenuListView for adding a swipe menu. Using a custom CursorAdapter, I populate the ListView with the name and total debt.
Now, I want to group each listview items depending on the due date. I've created a new column on my SQLite to add a header for each day. Now I just need to use different style for header and items of the ListView. By detecting the new column from bindView and depending on if it's a header or items, it will change, hide and show elements from the same layout.
The problem is that when I scroll the ListView, some of the listview items changed style. It get worse if I keep scrolling up and down. Here's the picture of the error from the listview. Notice that it's all in one session, the header style seems to have been used in some of the items and the header itself changed to red color which suppose to be color code for the items. If I click one of the item, it still get the correct item so I figure its a problem within the cursorAdapter but I just can't figure it out. It is not a mistake in the SQL database which I have checked.
Here's the cursorAdapter.
public class DebtCursorAdapterMain extends CursorAdapter {
public DebtCursorAdapterMain(Context context, Cursor c, int flags) {
super(context, c, flags);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.debt_list_item, parent, false);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
int x = Integer.parseInt(cursor.getString(cursor.getColumnIndex(DBHelper.DATE_SEPARATOR_COLUMN)));
TextView tvName = (TextView) view.findViewById(R.id.tvName);
TextView tvTotal = (TextView) view.findViewById(R.id.tvTotal);
if(x == 0) {
DecimalFormat df = new DecimalFormat("#.00");
String nameText = cursor.getString(cursor.getColumnIndex(DBHelper.NAME_COLUMN));
String totalText = "$ " + df.format(cursor.getDouble(cursor.getColumnIndex(DBHelper.TOTAL_COLUMN)));
String type = cursor.getString(cursor.getColumnIndex(DBHelper.TYPE_COLUMN));
if (tvName != null)
tvName.setText(nameText);
if (tvTotal != null)
tvTotal.setText(totalText);
if (type.equals("L"))
view.setBackgroundColor(Color.parseColor("#ff9999"));
if (type.equals("B"))
view.setBackgroundColor(Color.parseColor("#99ff99"));
}
if(x == 1){
String date = cursor.getString(cursor.getColumnIndex(DBHelper.DUE_DATE_COLUMN));
if (tvName != null && tvTotal != null) {
tvName.setText(date);
tvName.setTextSize(TypedValue.COMPLEX_UNIT_SP, 22);
tvTotal.setVisibility(View.GONE);
}
}
}
}
Here is the main activity in which the cursorAdapter is called.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Find SwipeMenuListView
final SwipeMenuListView swipeMenuList = (SwipeMenuListView) findViewById(R.id.swipeMenuList);
// Create Debt database cursor adapter
cursorAdapter = new DebtCursorAdapterMain(this, null, 0);
// Create SwipeMenuList and set item
SwipeMenuCreator creator = createMainActivitySwipeMenu();
swipeMenuList.setMenuCreator(creator);
swipeMenuList.setAdapter(cursorAdapter);
swipeMenuList.setSwipeDirection(SwipeMenuListView.DIRECTION_LEFT);
// Set SwipeMenuList on item's menu click
swipeMenuList.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {
....
}
});
// Swipe menu on Click function
swipeMenuList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
....
}
});
// Initialize cursor and check database for updating top info
getLoaderManager().initLoader(0, null, this);
checkDataBase();
}
I'm still new in android development so please tell me if there's a better approach to this problem. Thanks guys.

Android notifyDatasetChange with SQLite cursor how to?

So I have 2 activities.
The first (ActivityOne) displays a listview with data from SQLite cursor, and a button.
On click of that button, I want to add an item to the listview, so I display the second activity (ActivityTwo), that contains a number of editTexts and a save Button, that does the saving in the Database.
But what I want is:
after saving the new item to the DB, the ActivityTwo should close and the ActivityOne should be displayed with the refreshed content from the DB
.
This seems a reasonable workflow. How do I achieve it?
Code for ActivityOne:
public class ActivityOne extends Activity {
private ArrayList<String> idclient = new ArrayList<String>();
private ArrayList<String> numeclient = new ArrayList<String>();
private ArrayList<String> tipclient = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListView mylist = (ListView) findViewById(R.id.lv_clienti);
LoadList();
Button btnex = (Button) findViewById(R.id.btnNewCli);
btnex.setOnClickListener(
new View.OnClickListener()
{
public void onClick(View aView)
{
Toast.makeText(getApplicationContext(), "Add new client... " , Toast.LENGTH_SHORT).show();
Intent toAnotherActivity = new Intent(aView.getContext(), NewClientActivity.class);
startActivity(toAnotherActivity);
}
}
);
}
public void LoadList(){
SQLiteDatabase db = new myDbHelper(getApplicationContext()).getWritableDatabase();
Cursor mCursor = db.rawQuery("select idclient,nameclient,typeclient from clienti order by numeclient" , null);
idclient.clear();
numeclient.clear();
tipclient.clear();
if (mCursor.moveToFirst()) {
do {
idclient.add(Integer.toString(mCursor.getInt(0)));
nameclient.add(mCursor.getString(1));
typeclient.add(mCursor.getString(2));
} while (mCursor.moveToNext());
}
DisplayClientiAdapter disadpt = new DisplayClientiAdapter(ClientiActivity.this,idclient,nameclient, typeclient);
ListView lv = (ListView) findViewById(R.id.lv_clienti);
lv.setAdapter(disadpt);
mCursor.close();
db.close();
}
}
And in the ActivityTwo, I have in a button click:
db.execSQL("insert into clients (idclient, nameclient,typeclient,...");
DisplayClientiAdapter da = new DisplayClientiAdapter(getApplicationContext());
da.notifyDataSetChanged();
finish();
Also the displayAdapter is something like:
public class DisplayClientiAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<String> idclient;
private ArrayList<String> numeclient;
private ArrayList<String> tipclient;
public DisplayClientiAdapter(Context c){
this.mContext = c;
}
public DisplayClientiAdapter(Context c, ArrayList<String> idclient, ArrayList<String> numeclient, ArrayList<String> tipclient) {
this.mContext = c;
this.idclient = idclient;
this.numeclient = numeclient;
this.tipclient = tipclient;
}
public int getCount() {
return idclient.size();
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
public View getView(int pos, View child, ViewGroup parent) {
Holder mHolder;
LayoutInflater layoutInflater;
if (child == null) {
layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
child = layoutInflater.inflate(R.layout.clienti_item, null);
mHolder = new Holder();
mHolder.txt_idclient = (TextView) child.findViewById(R.id.tv_cl_id);
mHolder.txt_numeclient = (TextView) child.findViewById(R.id.tv_cl_nume);
mHolder.txt_tipclient = (TextView) child.findViewById(R.id.tv_cl_tip);
child.setTag(mHolder);
} else {
mHolder = (Holder) child.getTag();
}
mHolder.txt_idclient.setText(idclient.get(pos));
mHolder.txt_numeclient.setText(numeclient.get(pos));
mHolder.txt_tipclient.setText(tipclient.get(pos));
return child;
}
public class Holder {
TextView txt_idclient;
TextView txt_numeclient;
TextView txt_tipclient;
}
Of course it does not work like this. The list is not refreshed... I assume it has to do with the displayAdapter !?!?!
I cannot call the LoadList method since it is static or something like that...
Please help.
Thank you
Its not a problem with your adapter. You have to call Loadlist() in onresume method instead of oncreate method in ActivityOne. It will work then.
First of all, have a look at this two articles:
http://www.doubleencore.com/2013/05/layout-inflation-as-intended/
http://www.doubleencore.com/2013/06/context/
You shouldn't inflate your views with null in your inflate method if you have parent view available.
Also, using application context for inflating may cause strange behaviour, as it may not use correct theme you may've set in app manifest for your Activity.
On the other hand - why don't you use CursorAdapter instead of BaseAdapter?
The problem with your adapter is, that you don't set the data in it! :)
///EDIT:
I checked the wrong activity - why do you create second adapter in there?
The easiest solution would be to move the LoadList() to onStart.
If you want to do it right, you should use ContentObserver and (probably) CursorAdapter.

refresh listview after data has changed from custom adapter

I have seen several posts on this but I cannot seem to follow one well enough to fix my problem.
I am trying to refresh my ListView after I update or delete a record. I am currently using notifyDataSetChanged() however it does not refresh upon deletion. I can delete, and then if i back our and reload my history.java it will show the updates because I am reloading all of the data.
here is my HistoryAdapter.java
public class HistoryAdapter extends BaseAdapter {
private Context mContext;
Cursor cursor;
history historyClass = new history();
MySQLiteHelper db;
public HistoryAdapter(Context context, Cursor cur){
super();
mContext = context;
cursor = cur;
db = new MySQLiteHelper(context);
}
public int getCount(){
// return the number of records in cursor
return cursor.getCount();
}
// getView method is called for each item of ListView
public View getView(final int position, View view, ViewGroup parent){
// inflate the layout for each item of listView
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.history_list_item, null);
// move the cursor to required position
cursor.moveToPosition(position);
final String id = cursor.getString(cursor.getColumnIndex("_id"));
final long deleteId = Long.parseLong(id);
// fetch the information for each card
String pricePerGallon = cursor.getString(cursor.getColumnIndex("pricePerGallon"));
String gallons = cursor.getString(cursor.getColumnIndex("gallons"));
String odometer = cursor.getString(cursor.getColumnIndex("odometer"));
String date = cursor.getString(cursor.getColumnIndex("date"));
String filledOrNot = cursor.getString(cursor.getColumnIndex("filledOrNot"));
String comments = cursor.getString(cursor.getColumnIndex("comments"));
//String milesPerGallon = cursor.getString(cursor.getColumnIndex("miledPerGallon"));
String totalSpent = cursor.getString(cursor.getColumnIndex("totalSpent"));
// get the reference of TextViews
TextView textViewPricePerGallon = (TextView) view.findViewById(R.id.cardPrice);
TextView textViewGallons = (TextView) view.findViewById(R.id.cardGallons);
TextView textViewOdometer = (TextView) view.findViewById(R.id.cardOdometer);
TextView textViewDate = (TextView) view.findViewById(R.id.cardDate);
TextView textViewFilledOrNot = (TextView) view.findViewById(R.id.cardFilledOrNot);
TextView textViewComments = (TextView) view.findViewById(R.id.cardComments);
//TextView textViewMilesPerGallon = (TextView) view.findViewById(R.id.mpg);
TextView textViewTotalSpent = (TextView) view.findViewById(R.id.usd);
TextView textViewDeleteButton = (TextView) view.findViewById(R.id.deleteButton);
// Set the data to each TextView
textViewPricePerGallon.setText(pricePerGallon);
textViewGallons.setText(gallons);
textViewOdometer.setText(odometer);
textViewDate.setText(date);
textViewFilledOrNot.setText(filledOrNot);
textViewComments.setText(comments);
//textViewMilesPerGallon.setText(milesPerGallon);
textViewTotalSpent.setText(totalSpent);
final HistoryAdapter historyAdapter = this;
textViewDeleteButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Log.d("History Adapter", "" + deleteId);
//need to delete here
deleteRecord(deleteId);
historyAdapter.notifyDataSetChanged();
}
});
return view;
}
public Object getItem(int position){
return position;
}
public long getItemId(int position){
return position;
}
private void deleteRecord(long id){
db.deleteGasLog(id);
}
}
here is my history.java which sets the adapter and creates the listview
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.history);
context = this;
initViews();
cursor = db.getAllLogs();
// Create the Adapter
historyAdapter = new HistoryAdapter(this, cursor);
// Set the adapter to ListView
listContent.setAdapter(historyAdapter);
}
I guess you will need to get a new cursor.
Try moving this
cursor = db.getAllLogs();
into the adapter and call it again before the notifyDataSetChanged() call.
You are deleting the row but you are never updating or getting a new cursor, which has the result set the adapter uses to layout the list. You need to give the adapter a new cursor after you delete a row, then call notifyDatasetChanged(). If you use SimpleCursorAdapter
instead of BaseAdapter, you can use its swapCursor() method to set the new cursor.
Make sure to call:
registerDataSetObserver(...)
from your BaseAdapter subclass.
Pass it the reference to your DataSetObserver implementation. Possibly through an inner class of HistoryAdapter:
public class HistoryAdapter extends BaseAdapter {
. . .
public class MyDataSetObserver extends DataSetObserver {
public void onChanged() {
// Data Set changed.... do something...
}
public void onValidated() {
// Your implementation here
}
}
. . .
public HistoryAdapter(Context context, Cursor cur) {
. . .
registerDataSetObserver(new MyDataSetObserver());
. . .
}
}
HTH

Categories

Resources