2

I saw all the questions which is similar to my question ( in this , this , this and this link )

I had myAdapter.notifyDataSetChanged() in my Activity but it doesn't work

I have 3 classes,

  • DBHelper - For storing and getting Database contents ( NO ISSUES HERE )
  • SimpleRecyclerAdapter - Adapter for RecyclerList
  • ThirdActivity

What i did in ThirdActivity :

I have TextBox to get data and store it in Database and a Button. In the Onclicklistener of Button, i specified code to

  • get text from textbox
  • add it into table using DBHelper
  • retrive data as ArrayList from DBHelper
  • myAdapter.notifyDataSetChanged()

When i click the Button, I got Data in LogCat which i specified inside OnclickListener but it is not reflected to the listview.

Here is my code,

ThirdActivity:

public class ThirdActivity extends AppCompatActivity{

    private DrawerLayout mDrawerLayout;
    DbHelper dbHelper;

    EditText et;
    Button addButton;
    RecyclerView rv;
    ArrayList<String> myNotesList;
    SimpleRecycler3Adapter adapter3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.thirdactivity);
        myNotesList = new ArrayList<>();
        et=(EditText) findViewById(R.id.et);
        addButton=(Button)findViewById(R.id.addButton);
        rv = (RecyclerView) findViewById(R.id.dbListrv);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getBaseContext());
        rv.setLayoutManager(linearLayoutManager);
        rv.setHasFixedSize(true);

        adapter3 = new SimpleRecycler3Adapter(myNotesList);
        rv.setAdapter(adapter3);
        dbHelper = new DbHelper(this, null, null, 1);


        addButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("DB", "Constructor");
              String note=et.getText().toString();
             dbHelper.addNote(note);
               printData();
            }
        });
    }

    public void printData(){
        Log.d("DB","Constructor");
        myNotesList=dbHelper.databasetostring();
        Log.d("DB","Data came"+myNotesList.get(myNotesList.size()-1));
     //  adapter3 = new SimpleRecycler3Adapter(myNotesList);
       // rv.setAdapter(adapter3);
        adapter3.notifyDataSetChanged();
    }
}

SimpleRecyclerViewAdapter :

public class SimpleRecycler3Adapter extends RecyclerView.Adapter<SimpleRecycler3Adapter.NotesHolder> {

private  ArrayList<String> myNotesList=new ArrayList<String>();

        String TAG="ThirdAdapter kbt";
        RecyclerView rv;

    public SimpleRecycler3Adapter(ArrayList<String> myList) {
        Log.d(TAG,"Constructor");

            Log.d(TAG,"Not null");
            int i = 0;
            while (i < myNotesList.size()) {
                myNotesList.add(myList.get(i).toString());
            }
            Log.d(TAG,"finish");
    }


    @Override
        public NotesHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
          Log.d(TAG,"On create started");
        View view2 = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.recyclerlist3_item, viewGroup, false);
        Log.d(TAG,"ADAP STAR ONCR second switch 2nd line");
        NotesHolder viewHolder2 = new NotesHolder(view2);
        Log.d(TAG,"ADAP STAR ONCR second switch 3nd line");
        return viewHolder2;
        }

@Override
public void onBindViewHolder(NotesHolder notesHolder, int i) {
        Log.d(TAG, "ONBIND SECOND i value is " + i);


        // notesHolder.thumbnail.setImageResource(R.drawable.placeholder);

        notesHolder.dblistitem.setText(myNotesList.get(i));
          Log.d(TAG,"ONBIND second title issssss");


        }


@Override
public int getItemCount() {
        return myNotesList.size();
        }

class NotesHolder extends RecyclerView.ViewHolder {

    protected ImageView thumbnail;
    protected TextView dblistitem;
    public NotesHolder(View itemView) {
        super(itemView);
        Log.d(TAG, "JSON Inside HOLDER");
        rv=(RecyclerView)itemView.findViewById(R.id.dbListrv);
      //  thumbnail = (ImageView) itemView.findViewById(R.id.thumbnail);
        dblistitem = (TextView) itemView.findViewById(R.id.dblistitem);


    }

}

}
Community
  • 1
  • 1
Ganesh
  • 1,479
  • 1
  • 13
  • 36

5 Answers5

2

You're not updating the myNotesList that is in adapter class but in activity class. But the adapter uses it's local myNotesList.

So on button click, update myNotesList of adapter with latest data available and notify the adapter.

EDIT
Pass the latest data to adapter. Have this method in adapter class and call this before notifyDataSetChanged();

public void updateNotes(ArrayList<String> notesList) {
    myNotesList = notesList; 
}
cgr
  • 4,423
  • 2
  • 24
  • 48
  • How can i update it again, do i need to initialize again and again while inserting each element ? Or is there any way to update it. ? – Ganesh Dec 13 '15 at 08:30
  • 2
    You just need to pass the latest data to adapter. Have this method in adapter class and call this before notifyDataSetChanged(); public void updateNotes(ArrayList notesList) { myNotesList = notesList; } – cgr Dec 13 '15 at 08:37
  • I'll try it out and say you what is the result. – Ganesh Dec 13 '15 at 08:43
  • good. You do not need to vote up any answer before you make sure it helps you. It may lead to confusion for other seekers. :) You can accept answer. – cgr Dec 13 '15 at 08:53
  • 1
    They tried giving answers for me , i just appreciated and it made sense. Actually what they specified is correct (Generally nor for my answer ) That's why i up voted . Anyway... Thanks alot for the answer. I was sitting for 2 days with this error. lol... u solved it. Thanks again – Ganesh Dec 13 '15 at 08:59
  • Sure, makes sense for me too..not discouraging you. It's good you do that so they get boost ;) ha ha..2 days ;) – cgr Dec 13 '15 at 09:04
  • Yeah. I can't even get this simple idea :( My poor brain. – Ganesh Dec 13 '15 at 09:37
1

1.you are intializing your dbhelper after setting adapter to listview so it couldn't contain any data initially

2.for updating recycler view data list do as follows

myNotesList.clear();
myNotesList.addAll(dbHelper.databasetostring());
adapter3.notifyDataSetChanged();
Nas
  • 2,026
  • 16
  • 35
  • 1. Do i need to initialize before ? 2. If i do like that, i need to reload all the data whenever i add an item to listview. – Ganesh Dec 13 '15 at 08:14
  • Adding one item to the listview is better than reloading all the items for insertion of single item ? Correct me if i am wrong. – Ganesh Dec 13 '15 at 08:16
  • you are correct. use adapter3.notifyItemInserted(position); for updating particular item. – Nas Dec 13 '15 at 08:19
1

You have a problem in your SimpleRecyclerViewAdapter, just change this:

while (i < myNotesList.size()) {
    myNotesList.add(myList.get(i).toString());
}

For this:

myNotesList = myList;

And in your activity's printData() change:

myNotesList=dbHelper.databasetostring();

for this:

myNotesList.clear();
myNotesList.addAll(dbHelper.databasetostring());
adapter3.notifyDataSetChanged();

Explanation:

First you initialize myNotesList variable:

myNotesList = new ArrayList<>();

Then you initialize adapter3

adapter3 = new SimpleRecycler3Adapter(myNotesList);

But your adapter is not saving the reference, instead you're copying its data into another variable:

while (i < myNotesList.size()) {
    myNotesList.add(myList.get(i).toString());
}

Doing that, if you change myNotesList variable in your activity will not modify your adapter's dataset.

In your method printData() you change myNotesList variable. Which will not touch your adapter or its data

public void printData(){
    Log.d("DB","Constructor");
    myNotesList=dbHelper.databasetostring();
    Log.d("DB","Data came"+myNotesList.get(myNotesList.size()-1));
    //  adapter3 = new SimpleRecycler3Adapter(myNotesList);
    // rv.setAdapter(adapter3);
    adapter3.notifyDataSetChanged();
}
Santiago Hernández
  • 4,513
  • 1
  • 23
  • 33
  • So what changes i should do in my code to update my list? – Ganesh Dec 13 '15 at 08:19
  • 1
    Hi Ganesh, just put `myNotesList = myList;` instead of your `while`. This is in your `SimpleRecycler3Adapter`'s constructor and that's it – Santiago Hernández Dec 13 '15 at 08:21
  • While initializing only Adapter's constructor is called. After that note even a single time it is called as well as onBind onCreateViewHolder is also not called – Ganesh Dec 13 '15 at 08:28
  • I think it's because `dbHelper.databasetostring();` is returning a new `ArrayList` instance too – Santiago Hernández Dec 13 '15 at 08:32
  • Inside printData() i hided 2 lines. I un-hided it and the code works. I assume the method which you specified above will work, which one i should prefer. Which is the best practice, **initializing and setting adapter each time** or **your method**? – Ganesh Dec 13 '15 at 08:41
  • 1
    initializing an adapter every time the user tap on a button is not a good practice, that's why it's called `Recycler` – Santiago Hernández Dec 13 '15 at 08:43
  • I changed the two things which you specified above, but i can't see the list again. – Ganesh Dec 13 '15 at 08:45
  • I think you just need chang 1 place .where are the 2 places? – tiny sunlight Dec 13 '15 at 08:46
  • I got to go to sleep Ganesh, but good luck with that. I suggest you to declare a [setter](http://antonioleiva.com/recyclerview/) in your `adapter` so you can set the new `dataset` and call `notifyDataSetChanged` after setting it – Santiago Hernández Dec 13 '15 at 08:52
  • I mean in Adapter and printData () , anyhow cgr answer worked for me. Calling another method of Adapter for initialization purpose from ThirdActivity. – Ganesh Dec 13 '15 at 08:52
  • Look at comment of cgr's Answer, That one is good practice , isn't that? – Ganesh Dec 13 '15 at 08:53
  • actually yes it is :), that's the best way to go – Santiago Hernández Dec 13 '15 at 08:54
  • @SantiagoHernández Anyhow , thanks a lot for your explanation and effort for me. :) – Ganesh Dec 13 '15 at 08:58
0

You can't change myNotesList by changing myList.

   public SimpleRecycler3Adapter(ArrayList<String> myList) {
        Log.d(TAG,"Constructor");

            Log.d(TAG,"Not null");
          //  int i = 0;
           // while (i < myNotesList.size()) {
          //      myNotesList.add(myList.get(i).toString());
          //  }
            this.myNotesList = myList;
            Log.d(TAG,"finish");
    }
tiny sunlight
  • 6,096
  • 3
  • 18
  • 41
0

Not a good idea to call notifyDataSetChanged() when you know exactly what changed in your data collection. See this implementation here. They have even documented to use notifyDataSetChanged() as a last resort in this doc.

You get nice animations for free if you use methods like notifyItemInserted() and the rest.

Also do not go on replacing the collection object entirely, see the implmentation link that has been attached.

Community
  • 1
  • 1
razzledazzle
  • 6,635
  • 4
  • 24
  • 37