Listview is not getting updated with notifyDataSetChanged method - android

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.

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

Listview is not upadating after return from stand by

In my application i uses a thread to receive data and updates the listview in main activity. It works fine. But the phone goes sleep. After returning from sleep the listview in the main activity clears and data is not updated in listview. Refer following code
Main Activity
public class MainActivity extends Activity implements DeviceDiscovery.Listener {
private static final String TAG = "Main Activity";
static DeviceDiscovery mDeviceDiscovery = new DeviceDiscovery();
ArrayList<String> values=new ArrayList<String>();
ArrayAdapter<String> adapter;
ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, values);
listView = (ListView) findViewById(R.id.lvDevices);
listView.setAdapter(adapter);
if(!mDeviceDiscovery.isAlive()){
mDeviceDiscovery.setListener(this);
mDeviceDiscovery.start();
}
}
#Override
public void onDeviceDiscovery(final OV788DiscoveryPacket discoveryPacket,
final InetAddress IPAddress, final int Port) {
try {
String s;
s = " Camera Name : " + discoveryPacket.CameraName + "\n";
s += " Model Number : " + discoveryPacket.ModelNumber + "\n";
s += " Product Ver : " + discoveryPacket.ProductVersion + "\n";
Log.d(TAG, "" + s);
adapter.add(s);
} catch( Exception e ){
e.printStackTrace();
}
}
}
I think You should do this....Try and reply back if it works.
public class MainActivity extends Activity implements DeviceDiscovery.Listener {
private static final String TAG = "Main Activity";
static DeviceDiscovery mDeviceDiscovery = new DeviceDiscovery();
ArrayList<String> values=new ArrayList<String>();
ArrayAdapter<String> adapter;
ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(!mDeviceDiscovery.isAlive()){
mDeviceDiscovery.setListener(this);
mDeviceDiscovery.start();
}
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, values);
listView = (ListView) findViewById(R.id.lvDevices);
listView.setAdapter(adapter);
}
#Override
protected void onResume() {
super.onResume();
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, values);
listView.setAdapter(adapter);
}
}
#Override
public void onDeviceDiscovery(final OV788DiscoveryPacket discoveryPacket,
final InetAddress IPAddress, final int Port) {
try {
String s;
s = " Camera Name : " + discoveryPacket.CameraName + "\n";
s += " Model Number : " + discoveryPacket.ModelNumber + "\n";
s += " Product Ver : " + discoveryPacket.ProductVersion + "\n";
Log.d(TAG, "" + s);
values.add(s);
} catch( Exception e ){
e.printStackTrace();
}
}
}
Well I can't tell what is causing the data to clear from the given piece of code but you can try updating the list in onResume
Somthing like this:
#Override
protected void onResume() {
super.onResume();
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, values);
listView.setAdapter(adapter);
}
}
In your onDeviceDiscovery() method, add "adapter.notifyDataSetChanged();" after "values.add(s)".
The listview adapter should always be notified of data changes.
Firstly you have not shown or you have not initialized the ArrayList<String> values .
Then after you have initialized the ArrayList . and when you want to update the listview you have to use the method notifyDataSetChanged() .
in your case you have to use it like this-
.......
s += " Product Ver : " + discoveryPacket.ProductVersion + "\n";
Log.d(TAG, "" + s);
adapter.add(s);
adapter.notifyDataSetChanged(); //this will notify the listview that the data set is changed and will be updated in the listview.
} catch( Exception e ){
.......

how I can get the data from the selected item in the listView from my database and view it on alertdialog?

I am having trouble with a ListView I created:
I have a food database but how I can get the data from the selected item in the listView from my database and view it on alertdialog?
I can view the data but when I click any of it, my application will stop working.
My code for this looks like:
public class MainActivity extends AppCompatActivity {
ListView listView;
EditText editText;
private DatabaseHelperList dbHelper;
Adapter adapter;
ArrayList<Item> arrayList = new ArrayList<Item>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//loadDatabase
dbHelper = new DatabaseHelperList(this);
try {
dbHelper.checkAndCopyDatabase();
dbHelper.openDatabase();
} catch (SQLException e) {
}
try {
Cursor cursor = dbHelper.QueryData("select *from menulist");
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
Item item = new Item();
item.setId(cursor.getString(0));
item.setFood(cursor.getString(1));
item.setCalories(cursor.getString(2));
arrayList.add(item);
} while (cursor.moveToNext());
}
}
} catch (SQLException e) {
}
adapter = new Adapter(this, R.layout.custom_list_item, arrayList);
listView = (ListView) findViewById(R.id.list_item);
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View v, int position, long id)
{
Cursor res = dbHelper.getAllData("select " + position + " from menulist");
StringBuffer buffer = new StringBuffer();
while (res.moveToNext()) {
buffer.append("Weight: " + res.getString(1) + " kg \n");
buffer.append("BMI: " + res.getString(2) + "\n");
}
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setCancelable(true);
builder.setTitle("Confirmation:");
builder.setMessage(res.getInt(res.getColumnIndex("id")));
builder.setPositiveButton("YES", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent startNewActivity = new Intent(MainActivity.this, SQLiteDemoActivity.class);
startActivity(startNewActivity);
}
}).setNegativeButton("NO", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
builder.show();
}
}
);
}
}
This the log:
12-31 23:50:27.734 15775-15775/com.example.hidir.mnutrihealth E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.hidir.mnutrihealth, PID: 15775
android.database.CursorIndexOutOfBoundsException: Index 5 requested, with a size of 5
at android.database.AbstractCursor.checkPosition(AbstractCursor.java:426)
at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
at android.database.AbstractWindowedCursor.getInt(AbstractWindowedCursor.java:68)
at com.example.hidir.mnutrihealth.MainActivity$1.onItemClick(MainActivity.java:76)
at android.widget.AdapterView.performItemClick(AdapterView.java:299)
at android.widget.AbsListView.performItemClick(AbsListView.java:1162)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:2953)
at android.widget.AbsListView$3.run(AbsListView.java:3708)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:149)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
at dalvik.system.NativeStart.main(Native Method)
My first advice :
Create a class DAO for all the resquet into a database. Here, it will become unreadable if you add more than one call.
Second :
Are you sure that :
while (res.moveToNext()) {
buffer.append("Weight: " + res.getString(1) + " kg \n");
buffer.append("BMI: " + res.getString(2) + "\n");
}
Weight is a String and BMI a String too ?
If Weight is a int or a double, i think you have to use res.getInt(1) or res.getDouble(1). Check the real method, i don't remember is you have to specify the "column name"
Edit : I think i found the issue :
while (res.moveToNext()) {
buffer.append("Weight: " + res.getString(1) + " kg \n");
buffer.append("BMI: " + res.getString(2) + "\n");
}
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setCancelable(true);
builder.setTitle("Confirmation:");
builder.setMessage(res.getInt(res.getColumnIndex("id")));
look at the last line. You would like to have the integer of something, but the cursor is now a the end of the list of item that were asking before.
You do :
A while loop for putting all the element on a StringBuffer, and when it finish, you ask a another time to access to a element that doesn't exist anymore.
Answer is in the Log. It says, CursorIndexOutOfBoundsException: Index 5 requested, with a size of 5 at com.example.hidir.mnutrihealth.MainActivity$1.onItemClick(MainActivity.java:76).
The problem is here,
builder.setMessage(res.getInt(res.getColumnIndex("id")));
At the time when you call the method res.getInt(), size of cursor is 5 (means index values from 0 to 4) but it is pointing at index 5. That's why it is throwing CursorIndexOutOfBoundsException.

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

Android setonitemclicklistener implementation

I have a ArticlesAdapter which I am using to read remote JSON data. The adapter is working but I am struggling to get my ListView setonitemclicklister working.
What I am trying to accomplish is the ability to click on a ListItem and to get the Article data for the option clicked on.
I have functions like getName() in my Article class which I need to call in response to a ListItem click but I can't seem to find a way to accomplish it.
I am trying to do this in my AsyncTask class.
Using the following code:
protected void onPostExecute(JSONArray result) {
// TODO Auto-generated method stub
Log.i("CHECK", "RESULTS: " + result);
List<Article> articles = new ArrayList<Article>();
String title = null;
String nid = null;
try{
for(int i=0; i < data.length(); i++){
JSONObject dataObj = (JSONObject)data.get(i);
JSONObject record = dataObj.getJSONObject("node");
title = (record.getString("title"));
nid = (record.getString("nid"));
Log.i("FOUND", "title: " + title);
Log.i("FOUND", "nid: " + nid);
articles.add( new Article(title, "", Integer.parseInt(nid)) );
}
}catch(JSONException j){
Log.e("CHECK", "Attempting to read data returned from JSONReader: " + j.toString());
}
ListView articlesList = (ListView)findViewById(R.id.articlesList);
ArticleAdapter adapter = new ArticleAdapter(ArticlesActivity.this, R.layout.article_item, articles);
articlesList.setAdapter(adapter);
articlesList.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "testing : ", Toast.LENGTH_LONG);
Log.i("CHECK", "AdapterView: " + parent);
Log.i("CHECK", "VIEW : " + view);
Log.i("CHECK", "POSITION : " + position);
Log.i("CHECK", "ID : " + id);
}
});
if(dialog.isShowing())
dialog.dismiss();
}
My problem is I am not sure how to get the setOnItemClickListener working.
I am able to print the arguments via the Log function:
Log.i("CHECK", "AdapterView: " + parent);
Log.i("CHECK", "VIEW : " + view);
Log.i("CHECK", "POSITION : " + position);
Log.i("CHECK", "ID : " + id);
...but I get errors when I try casting any of the arguments into an Article object so I can call it's getName() function etc.
Your AsyncTask appears to be nested in your Activity, if it isn't simply pass articles to your Activity, then use:
articlesList.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
Article article = articles.get(position);
// Do something with article
}
});
An architectural change you would want to do is pull your ListView, Adapter, and OnItemClickListener initialization out of the AsyncTask and only update articles as well as notify the Adapter in the onPostExecute callback.

Categories

Resources