Refresh ListView from ArrayAdapter
Asked Answered
C

4

6

I'm using ArrayAdapter to bind my data from my ArrayListto my ListView and i use an AlertDialogto insert data into my Arraylist. My problem is that i'm unable to refresh my ListView after the changes done.

Code

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.config_hidden);
    listView=(ListView) findViewById(R.id.hiddenList);
    xmlFileManager=new XmlFileManager(this);
    addNumber=(Button) findViewById(R.id.addNum);

    addNumber.setOnClickListener(new OnClickListener() {

        public void onClick(View arg0) {

            LayoutInflater factory = LayoutInflater.from(HiddenCall.this);
            final View alertDialogView = factory.inflate(R.layout.add_number, null);
            AlertDialog.Builder adb = new AlertDialog.Builder(HiddenCall.this);
            adb.setView(alertDialogView);
            adb.setTitle(R.string.dialog_title);
            adb.setIcon(R.drawable.phone);

            final AlertDialog alertDialog = adb.create();

            adb.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    numberToAdd=(EditText) alertDialogView.findViewById(R.id.numberToAdd);
                    String number = numberToAdd.getText().toString();
                    if(number.length()>0){
                        xmlFileManager.addNumberToXml(number , HIDDEN_NUMBER_TYPE);
                        adapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, xmlFileManager.getHiddenNumbers());
                        adapter.setNotifyOnChange(true);
                        adapter.notifyDataSetChanged();
                    }
                } });

            adb.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    alertDialog.dismiss();
                } });
            adb.show();
        }
    });
    adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, xmlFileManager.getHiddenNumbers());
    adapter.notifyDataSetChanged();
    adapter.setNotifyOnChange(true);
    listView.setAdapter(adapter);
}
Curvy answered 2/8, 2012 at 21:27 Comment(3)
why are you creating a new adapter each time instead of modifying the existing one? your calls to notifyDataSetChanged() are useless if you just created the adapter..Delogu
Another thing I see you are missing is to set the adapter to the listview...Amphora
I posted the code, hope it helps. You still need to add some sort of setter to the adapter and pass there the updated data.Amphora
A
8

You are instantiating a new adapter each time. What you have to do is put the line where you instantiate the adapter before the click listener, and in the click listener modify that adapter and call notifyDataSetChanged() on it. You of course have to add some setters to your adapter in order to modify the data.

Has to look similar to this:

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.config_hidden);
listView=(ListView) findViewById(R.id.hiddenList);

//instantiate the adapter (just one time)
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, xmlFileManager.getHiddenNumbers());

//assign the adapter to the listview
listView.setAdapter(adapter);

xmlFileManager=new XmlFileManager(this);
addNumber=(Button) findViewById(R.id.addNum);

addNumber.setOnClickListener(new OnClickListener() {

    public void onClick(View arg0) {

        LayoutInflater factory = LayoutInflater.from(HiddenCall.this);
        final View alertDialogView = factory.inflate(R.layout.add_number, null);
        AlertDialog.Builder adb = new AlertDialog.Builder(HiddenCall.this);
        adb.setView(alertDialogView);
        adb.setTitle(R.string.dialog_title);
        adb.setIcon(R.drawable.phone);

        final AlertDialog alertDialog = adb.create();



        adb.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                numberToAdd=(EditText) alertDialogView.findViewById(R.id.numberToAdd);
                String number = numberToAdd.getText().toString();
                if(number.length()>0){
                    xmlFileManager.addNumberToXml(number , HIDDEN_NUMBER_TYPE);
                    //adapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, xmlFileManager.getHiddenNumbers());
                    //adapter.setNotifyOnChange(true);

                    //set the changed data
                    adapter.setData(xmlFileManager.getHiddenNumbers());

                    //notify that the model changed
                    adapter.notifyDataSetChanged();
                }
            } });

        adb.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                alertDialog.dismiss();
            } });
        adb.show();
    }
});

//adapter.notifyDataSetChanged();
//adapter.setNotifyOnChange(true);
Amphora answered 2/8, 2012 at 21:33 Comment(5)
@lxx ArrayAdapterdoesn't have the method setDataCurvy
Ah, yes, you actually don't have to set the data in the ArrayAdapter. It should be enough to update the underlying array, which you are already doing addNumberToXml(). So just remove the setData() line. Tell me if that works.Amphora
I assume the hidden numbers array passed to the xmlFileManager is always the same. If the instance is created again the changes will not be noticed by the adapter.Amphora
I tried to call notifyDataSetChangedbut it seems it doesn't take the change in consideration. To resolve this problem i preferred create a ListAdapterthat extends BaseAdapter and now it's working. Thanks for your reply .Curvy
Yes, that was the plan B which I was going to tell you if you say me that the array adapter doesn't show the changes. You should post the complete code, there's no way to know if the array you're passing is always the same reference or not. And anyways, this answer shows you the principle of using an adapter (also applies for custom adapter) and I deserve at least +1. No way to tell you the exact solution if you don't post complete code.Amphora
P
4

If you have a small ArrayList, to force update a ListView when the ArrayList changes you can use this code snippet:

ArrayAdapter.clear();
ArrayAdapter.addAll(ArrayList);
ArrayAdapter.notifyDataSetChanged();
Palmate answered 4/3, 2017 at 9:32 Comment(1)
What do you mean by "small"? It looks ok even for large lists (10 000 items). Of course it is not a good practise to refresh the whole list after updating only one item (for example). The app architecture made me to use it for now. :-)Professoriate
J
0

Every click you create new adapter. You don't need to do this. You can modify existing adapter data and call notifyDataSetChanged(). In your case you should call listView.setAdapter(adapter) in onClick method.

Jihad answered 2/8, 2012 at 21:32 Comment(2)
@lxx shouldn't he set the adapter in onCreate() and just modify it in onClick() ?Delogu
That's what I'm saying, create and set once, and modify in onClick() (and call notifyDataSetChanged()).Amphora
A
0

Inside your adb.setPositiveButton()'s onClick(), you should not create a new adapter. Remove this line:

adapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, xmlFileManager.getHiddenNumbers());

Simply do this:

if(number.length()>0){
    xmlFileManager.addNumberToXml(number , HIDDEN_NUMBER_TYPE);
    adapter.notifyDataSetChanged();
}
Antipyretic answered 2/8, 2012 at 22:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.