Can't access notifyDataSetChanged - android

I have a ListView that I update from my SQLite database and I have set an onItemLongClickListener to help me delete from my database through a dialog interface. However, I can't seem to have access to notifyDataSetChanges not even if I make my adapter global.
This is my list population function
private void populateListView() {
Cursor data = mDatabaseHelper.getData();
ArrayList<String> listdata = new ArrayList<>();
while (data.moveToNext()) {
last_date = expire_Date(data.getString(4));
Calendar c = Calendar.getInstance();
c.setTime(last_date);
c.add(Calendar.DATE, 30);
Date currDate = new Date();
SimpleDateFormat dates = new SimpleDateFormat("M/d/yyyy");
currDate.setTime(System.currentTimeMillis());
int differenceDates;
differenceDates = difOfDay(c, currDate);
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
int day = c.get(Calendar.DAY_OF_MONTH);
month = month+1;
String date = month + "/" + day + "/" + year;
String first_row =data.getString(3) + " (" + data.getString(1) + ")\n";
String second_row = getResources().getString(R.string.red_info);
listdata.add(first_row + " " + second_row + differenceDates + " (" + date + ")");
}
ListAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,listdata);
mListView.setAdapter(adapter);
}
And this is my delete function:
public AdapterView.OnItemLongClickListener myClickListener = new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view,final int position, final long id) {
AlertDialog alert = new AlertDialog.Builder(view.getContext())
.setTitle("Delete ")
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
mDatabaseHelper.deletechute(position);
Toast.makeText(getApplicationContext(), "Parachute deleted", Toast.LENGTH_LONG).show();
adapter.notifyDataSetChanged(); ////Here my code can't resolve my adapter///
dialog.dismiss();
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
}).show();
return false;
}
};

This just looks firstly like a plain Java Variable scope problem but there are other problems as well but it is very hard to tell without more code.
So.
Problem 1
The adapter is defined and initialized in the scope of populateListView.
When this method ends, the reference is removed and the variables memory area can be deleted by garbage collection.
I suggest you read https://www.java-made-easy.com/variable-scope.html
You could fix this by defining the adapter as a private variable in the scope of your Activity Class and then it will be available to all methods in the class.
Problem 2
If you have fixed Problem 1 then adapter.notifyDataSetChanged(); still won't do anything.
This is because you are notifying it that the ArrayList<String> listdata has changed when you have done nothing to update the List and you cannot update it because again there is not available reference to listdata because it was also defined in local scope.
This again could be fixed by making listdata a private variable in the scope of your Activity but that leads to:-
Problem 3
This is a very convoluted way of doing this having to keep the database and list in sync manually.
You would be better off with a Cursor Adapter e.g. https://developer.android.com/reference/android/widget/SimpleCursorAdapter.html
A guide on Cursor Adapters with Listviews at https://github.com/codepath/android_guides/wiki/Populating-a-ListView-with-a-CursorAdapter
Then in the OnClick method you would update your database, and get a new Cursor of all the results again and swap the new Cursor for the old and then adapter.notifyDataSetChanged();

Related

Get primary key when clicking on one item on listview

If I populate my listview with the primary key of my table I can get this primary key using getItemAtPosition and then it works fine.
The problem is that I don't want to use the primarykey to populate de listview, instead I want to use other fields of my table. Doing that, when I use the getItemAtPosition comand, because itsn't unic I can't use this to select my register.
I thought about using getItemIdAtPosition but I didn't reached any solution.
public void populateListView() {
//get the data and append to the list
Cursor data = db.getAllDataFillup(selectedID);
ArrayList<String> listData2 = new ArrayList<>();
while (data.moveToNext()) {
//listData2.add("FILLUP_ID: " + data.getString(0) + " FILLUP_VEHICLE_ID: " + data.getString(1));
//listData2.add(data.getString(7) + " " + data.getString(8) + " " + data.getString(2));
listData2.add(data.getString(3));
//listData2.add(data.getString(2));
}
//create the list adapter and set the adapter
ListAdapter adapter2 = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, listData2);
list_fillup.setAdapter(adapter2);
//set onItemClickListener to the listView
list_fillup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
int fillupID = Integer.parseInt(adapterView.getItemAtPosition(i).toString());
long position = adapterView.getSelectedItemId();
//long a = list_fillup.get(codigoDoObjeto).getCodigoIdOuPKQualquer();
toastMessage("position: " + position);
//toastMessage("fillupPosition: " + fillupPosition);
//long fillupPosition = adapterView.getItemIdAtPosition(i);
Log.d(TAG, "onItemClick: You Clicked on " + fillupID);
Cursor data = db.getDataTableFillup(fillupID);//get the data associated with that fillupID
fillupID = -1;
while (data.moveToNext()) {
fillupID = data.getInt(0);
vehicleID = data.getInt(1);
fillupDate = data.getString(2);
odometer = data.getLong(3);
kmDriven = data.getLong(4);
liters = data.getLong(5);
consumption = data.getLong(6);
label = data.getString(7);
sequence = data.getInt(8);
}
if (fillupID > -1) {
Log.d(TAG, "onItemClick: The ID is: " + fillupID);
Intent screenVehicle = new Intent(Vehicle_painel.this, Fillup_edit.class);
screenVehicle.putExtra("fillupID", fillupID);
screenVehicle.putExtra("vehicleID", vehicleID);
screenVehicle.putExtra("vehicleName", selectedName);
screenVehicle.putExtra("date", fillupDate);
screenVehicle.putExtra("odometer", odometer);
screenVehicle.putExtra("kmDriven", kmDriven);
screenVehicle.putExtra("liters", liters);
screenVehicle.putExtra("consumption", consumption);
screenVehicle.putExtra("label", label);
screenVehicle.putExtra("sequence", sequence);
//toastMessage("fillupPosition: " + fillupPosition);
startActivity(screenVehicle);
} else {
toastMessage("fillupID = " + fillupID);
//db.deleteAllFillup(selectedID);
//toastMessage("No ID associated with that name hahaha");
}
The best thing to do would be to create a custom class to hold your data. That way you no longer just get a simple String value back from your adapter. Your ArrayList would be something like:
ArrayList<YourCustomClass> listData2 ...
Create a custom class "YourCustomClass" (Call it what ever you like). It could look like:
public class YourCustomClass {
private long itemId = 0;
private String itemName;
private String itemDescription;
public YourCustomClass(){
}
public void setItemId(long id){ this.itemId = id; }
public void setItemName(String itemName){ this.itemName = itemName; }
public void setItemDescription(String itemDescription){ this.itemDescription = itemDescription; }
public long getItemId() { return this.itemId; }
public String getItemName(){ return this.itemName; }
public String getItemDescription(){ return this.itemDescription; }
}
Now in your onItemClick method get the Id and the other data like this:
YourCustomClass data = (YourCustomClass) adapterView.getItemAtPosition(i);
long orderId = data.getItemId();
String name = data.getItemName();
You will need a custom adapter to populate your ListView with data.
You can also take a look at this answer. It shows how to change the background color of a ListView item, but also shows more detail of how to implement a custom adapter for your ListView.
How to set background color for each item listview depanding on variable value

AlertDialog not loading

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()

Update Listview after deleting database item

Ive been trying to get my listview to update after removing an item. Here's what I have so far:
myList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
String str = null;
public void onItemClick(AdapterView<?> arg0, final View view, int arg2, long arg3) {
//TextView txtview = (TextView)view.findViewById(R.id.txtview);
final String item = ((TextView) view.findViewById(R.id.txtview)).getText().toString();
str = item;
final long arr = arg3;
final String arg22 = longToString(arg3);
//Creating an Alert Dialog
AlertDialog.Builder builder = new AlertDialog.Builder(Home.this);
builder.setMessage("Are you sure you want to delete the hike " + str + " ?");
builder.setCancelable(false);
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
SQLiteDatabase db1=openOrCreateDatabase("hikeManager", MODE_PRIVATE, null);
DatabaseHandler db = new DatabaseHandler(Home.this);
String table = "hikes";
Cursor c = db1.rawQuery("select id from "+ table + " where name='"+item+"'", null);
int dhike = c.getColumnIndex("name") + 1;
try {
Hike hike = db.getHike(arr + 1);
db.deleteHike(hike);
Log.d("DLT", "Deleted hike at index " + arr);
//db.updateList(adapter, myList, listItems);
adapter.remove(arg22);
adapter.notifyDataSetChanged();
//updateData();
db.close();
} catch (CursorIndexOutOfBoundsException e) {
Log.d("DLT", "Failed to delete: " + e.getMessage());
db.close();
}
//db.updateList(adapter, myList, listItems);
}
});
builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
});
I Have quite a bit of unused code in there, as I have tried a few different methods to get this to work, but have failed so far. Here is updateData:
private void updateData() {
// Get all of the notes from the database and create the item list
DatabaseHandler db = new DatabaseHandler(this);
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, R.id.txtview, listItems);
final ListView myList = (ListView) findViewById(R.id.cardListView);
int num = db.getHikesCount();
for (int i=1; i<num+1; ++i){
Hike name = db.getHike(i);
String nam = name.getName();
listItems.add(nam);
}
myList.setAdapter(adapter);
db.close();
}
The updateData does have some unintended consequences when I use it to update the view after adding an item to a non-empty list, but it works for now. The item is successfully deleted, since I can close the app and reload it and the item will be gone. I just cant seem to get it to update properly for me.
Just use
adapter.notifyDataSetChanged();

Listview is not getting updated with notifyDataSetChanged method

I am trying to update my listview with notifyDataSetChanged() this method, but listview is not getting updated, if i press back button and go to previous activity and then again if i come in this activity then it is getting updated, i don't know why. I tried all possible solution but not getting proper solution. Please help Below is my code.
Here is a link which i tried
ListView not getting updated on calling notifyDataSetChanged()
notifyDataSetChanged() not working
notifyDataSetChanged Android ListView
notifyDataSetChanged not updating ListView
The event of notifyDataSetChanged()
public class Assignment extends Activity {
ListView mListView;
ImageView imageViewCrtAsnm;
String[] stg1;
List<String[]> names2 = null;
DataManipulator dataManipulator;
ArrayAdapter<String> adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.assignment);
imageViewCrtAsnm = (ImageView) findViewById(R.id.createassignment);
mListView = (ListView) findViewById(R.id.displaydata);
imageViewCrtAsnm.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(Assignment.this,
Assignment_Create.class);
startActivity(intent);
}
});
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View item,
final int position, long id) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
Assignment.this);
alertDialogBuilder.setTitle("Delete Data");
alertDialogBuilder
.setMessage("Click yes to Delete Record!")
.setCancelable(false)
.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int id) {
String[] delete = names2.get(position);
String idString = delete[0];
long idLong = Long.valueOf(idString);
Log.d("Deleting...", idLong + "");
dataManipulator.delete(idLong);
names2.remove(position);
stg1 = new String[names2.size()];
int x = 0;
String stg;
for (String[] name : names2) {
stg = "Title : " + name[1] + "\n"
+ "Descr : " + name[2]
+ "\n" + "Day's Left : "
+ name[3];
stg1[x] = stg;
x++;
}
adapter.notifyDataSetChanged();
}
})
.setNegativeButton("No",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int id) {
// if this button is clicked, just close
// the dialog box and do nothing
dialog.cancel();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
});
dataManipulator = new DataManipulator(this);
names2 = dataManipulator.selectAll();
stg1 = new String[names2.size()];
int x = 0;
String stg;
for (String[] name : names2) {
stg = "Title : " + name[1] + "\n" + "Descr : " + name[2] + "\n"
+ "Day's Left : " + name[3];
stg1[x] = stg;
x++;
}
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, stg1);
mListView.setAdapter(new ArrayAdapter<String>(this, R.layout.check,
stg1));
mListView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}
ArrayAdapter makes a copy of your items that you pass to it in the constructor and uses that internally.
ArrayAdapter Source
So simply manipulating your original array means nothing to the adapter. You are notifying it that the data has changed when it has not changed at all, it still holds the original list you populated it with.
You need to either recreate the entire adpater again or use the clear, addAll, remove or insert methods to manipulate the data.
http://developer.android.com/reference/android/widget/ArrayAdapter.html
You are recreating your array when you remove data. Have you tried also recreating your adapter to use the new array?
I found solution for this.
Just use onResume method to call adapter class...
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
names2 = dataManipulator.selectAll();
stg1 = new String[names2.size()];
int x = 0;
String stg;
for (String[] name : names2) {
stg = "Title : " + name[1] + "\n" + "Descr : " + name[2] + "\n"
+ "Day's Left : " + name[3];
stg1[x] = stg;
x++;
}
adapter = new ArrayAdapter<String>(this, R.layout.assignment_custom,
stg1);
mListView.setAdapter(adapter);
mListView.setCacheColorHint(Color.TRANSPARENT);
mListView.setBackgroundResource(R.drawable.assignment_icon);
adapter.notifyDataSetChanged();
adapter.setNotifyOnChange(false);
mListView.invalidateViews();
}
Just call this part of code in onResume method and you are done. But anyway thanks to all who have helped me. i am posting this answer here so may be other's can take benefit and not waste time like i did.

how to display items i want on a toast?

my first time doing an app on android. i have 4 strings and a lisview.i want to display the strings whenever user press the items on the listview on a toast.
can any one help me on this ?
For eg: there are Event 1 ,event 2 and event 3 on my list view.
and when user press event 1. it will display the date, time , venue for that event.
listview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
Context context = getApplicationContext();
Toast.makeText(context,
"Date: "+date +" " +"Tme: "+ time, Toast.LENGTH_LONG).show();
Toast.makeText(context,"hi",Toast.LENGTH_LONG).show();
}
});
This is the codes for extracting it out from googleCalendar
date = contentResult[0].substring(10, 21);
time = contentResult[0].substring(21, 36);
location = contentResult[2].substring(6);
description = contentResult[4].substring(18);
eventTitle[i] = name;
eventDate[i] = date;
eventTime[i] = time;
eventVenue[i] = location;
eventContent[i] = description;
event[i] = name + " " + "Date: " +date + " " + "Time: " +time + " " +" Location:"+ location+ "Event Description:"+ description ;
You would need to set your lists onItemClickListener like so:
private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id)
{
// Display a messagebox.
Toast.makeText(this,"You clicked something!",Toast.LENGTH_SHORT).show();
}
};
myList.setOnItemClickListener(mMessageClickedHandler);
Of course you would have to input your own data (I'm guessing from a database or web service) to the Toast message indicating the date, time, and location of the event.
EDIT: In response to your comment, it sounds like you are new to Android development. You might want to check out this great tutorial to learn how to use SQLite, and the Android SDK in general.

Categories

Resources