androidlistview

where to place notifyDataSetChanged(); in customAdapter so listView doesn't lose data on scroll


I know there is information online about notifyDataSetChanged(); and how to use it but I can't seem to be able to figure out how to use it for my exact situation. I don't know if I should call it in my activity, adapter class or what. I just want the listView to not change the text the user previously inputted to go back to the default text when the row scrolls off the screen.

MainActivity.java

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.app.Activity;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ViewSwitcher;

import java.util.ArrayList;

public class MainActivity extends Activity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final ArrayList<String> Chores = new ArrayList<>();
        Chores.add("");

        final ListAdapter MyAdapter = new CustomAdapter(this, Chores);
        ListView listViewObject = (ListView)findViewById(R.id.customListView_ID);
        listViewObject.setAdapter(MyAdapter);

        listViewObject.setOnItemClickListener(
            new AdapterView.OnItemClickListener(){
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id){
                    String ChoreString = String.valueOf(parent.getItemAtPosition(position));




                }
            }

        );
        final Button button = (Button) findViewById(R.id.button_ID);
        button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Chores.add("");
                ((ArrayAdapter)MyAdapter).notifyDataSetChanged();

            }

        });




    }
}

CustomAdapter.java

import android.content.Context;
import android.content.DialogInterface;
import android.support.annotation.NonNull;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;

import static com.example.emilythacker.chorelist.R.id.textView_ID;



class CustomAdapter extends ArrayAdapter{

    public CustomAdapter(Context context, ArrayList choreText) {
        super(context, R.layout.custon_listview_row, choreText);
    }

    @NonNull
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater myInflater = LayoutInflater.from(getContext());
        View customView = myInflater.inflate(R.layout.custon_listview_row, parent, false);


        ImageButton imageButton = (ImageButton) customView.findViewById(R.id.imageButton_ID);
        final TextView textView = (TextView) customView.findViewById(textView_ID);





        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //what happens when textView is clicked
                AlertDialog alertDialog = new AlertDialog.Builder(getContext()).create();
                final EditText input = new EditText(getContext());
                input.setHint("hint");
                alertDialog.setView(input);
                alertDialog.setTitle("Set Chore");
                alertDialog.setMessage("Alert message to be shown");
                alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {

                                //this will set text to "hello" only if user does not enter anything into input
                                //textView.setText("hello");

                                //this also will only work if there is no input entered into input...which will change textView into empty space
                                textView.setText(input.getText().toString());




                                //works the same with or without dialog.dismiss();
                                dialog.dismiss();
                            }
                        });
                alertDialog.show();

            }
        });



        imageButton.setImageResource(R.drawable.clock);


        return customView;
    }
}

Solution

  • The problem is not caused by notifyDataSetChanged(); but because you are not reusing your view in your adapter and not setting the data you want to set in your getView()

    Better try to use viewholder pattern or use recyclerview.

    class CustomAdapter extends ArrayAdapter{
    
        ArrayList<String> choreText;
    
        public CustomAdapter(Context context, ArrayList choreText) {
            super(context, R.layout.custon_listview_row, choreText);
            this.choreText = choreText;
        }
    
        @NonNull
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null) {
                LayoutInflater layoutInflater = LayoutInflater.from(getContext());
                convertView = layoutInflater.inflate(R.layout.custon_listview_row, parent, false);
                holder = new ViewHolder();
                holder.imageButton = (ImageButton) customView.findViewById(R.id.imageButton_ID);
                holder.textView = (TextView) customView.findViewById(textView_ID);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
    
            holder.textView.setText(choreText.get(position));
            holder.textView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //what happens when textView is clicked
                    AlertDialog alertDialog = new AlertDialog.Builder(getContext()).create();
                    final EditText input = new EditText(getContext());
                    input.setHint("hint");
                    alertDialog.setView(input);
                    alertDialog.setTitle("Set Chore");
                    alertDialog.setMessage("Alert message to be shown");
                    alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK", new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int which) {
    
                                    //this will set text to "hello" only if user does not enter anything into input
                                    //textView.setText("hello");
    
                                    //this also will only work if there is no input entered into input...wich will change textView into empty space
                                    textView.setText(input.getText().toString());
    
    
    
    
                                    //works the same with or without dialog.dismiss();
                                    dialog.dismiss();
                                }
                            });
                    alertDialog.show();
    
                }
            });
    
    
    
            holder.imageButton.setImageResource(R.drawable.clock);
    
    
            return customView;
        }
    
        static class ViewHolder {
            ImageButton imageButton;
            TextView textView;
        }
    }