Notifydatasetchanged() Makes the List Refresh and Scroll Jumps Back to the Top

notifyDataSetChanged() makes the list refresh and scroll jumps back to the top

Such behaviour is not normal. Without seeing your code I can suggest following:

1) You are not calling notifyDataSetChanged() from the UI thread. The correct way:

runOnUiThread(new Runnable() {
public void run() {
adapter.notifyDataSetChanged();
}
});

2) You accidentally or not are making a call to adapter.notifyDataSetInvalidated();

3) In your adapter you override the adapter.notifyDataSetChanged(); method and added instruction to go to top

4) If you're using a list to populate adapter - you supply new list every time, so adapter settings are refreshed. You should always supply the same list. However you can change it as much as you want. If you're resetting the list use list.clear instead of list = new ArrayList();

Here is an example of my adapter:

public class Adapter extends BaseAdapter {

private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater = null;
public ImageLoader imageLoader;

public MediaItemAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
data = d;
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader = new ImageLoader(activity.getApplicationContext());
}

public int getCount() {
return data.size();
}

public Object getItem(int position) {
return position;
}

public long getItemId(int position) {
return position;
}

public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
if (convertView == null) {
vi = inflater.inflate(R.layout.item_composer, null);
}
TextView title = (TextView) vi.findViewById(R.id.item_title); // title
TextView price = (TextView) vi.findViewById(R.id.price);


return vi;
}


}

Call for adapter:

List myList = new ArrayList<HashMap<String, String>>();
Adapter ma = new Adapter(this, myList);

myList can be empty before adapter initialization.

Then do some operation with my list:

myList.add(someElement);
ma.notifyDataSetChanged();

if you need delete all items:

myList.clear();
ma.notifyDataSetChanged();

Such implementation is pretty endless, I saw more then 15 thousand elements without any problems.

notifyDataSetChanged() makes the list refresh and scroll jumps back to the top of list

PhotofargmentAdapteryoumay adapter3 = new PhotofargmentAdapteryoumay(MainActivity.this, home_youmay_filepath);
listViewyoumay.setAdapter(adapter3);

Remove this lines

On updation of data set of recycler view list ,it's scroll jumps back to the top (duplicate)

I have just use SwipeRefreshLayout which was solved my issue.

Visit https://developer.android.com/training/swipe/add-swipe-interface

notifyDataSetChanged() forces scroll up in FragmentStatePagerAdapter

EDIT:

I've created a demo project. Here are some important pieces.

  1. Use a FragmentStatePagerAdapter subclass.

    We need a FragmentStatePagerAdapter base class in order to save the state of the fragment.

  2. Save the scroll position of the ScrollView in onSaveInstanceState(), and set the scroll position to the saved value when the fragment view is (re)created.

    Now that we are saving/restoring the fragment state, we put the scroll position in that state:

        @Override
    public void onSaveInstanceState(Bundle outState) {
    int scrollY = scrollView.getScrollY();
    outState.putInt("scrollY", scrollY);
    super.onSaveInstanceState(outState);
    }

    and restore it in onCreateView():

            if (savedInstanceState != null) {
    final int scrollY = savedInstanceState.getInt("scrollY");
    scrollView.post(new Runnable() {
    @Override
    public void run() {
    scrollView.setScrollY(scrollY);
    }
    });
    }
  3. Set up a listener notification system for updates.

    We have an interface called DataUpdateListener that is implemented by the fragment. The activity provides register/unregister methods:

    public void addDataUpdateListener(DataUpdateListener listener) {
    mListenerMap.put(listener.getPage(), listener);
    }

    public void removeDataUpdateListener(DataUpdateListener listener) {
    mListenerMap.remove(listener.getPage());
    }

    ... and the fragment registers & unregisters with the activity:

    in onCreateView():

        ((MainActivity) getActivity()).addDataUpdateListener(this);

    also

        @Override
    public void onDestroyView() {
    ((MainActivity) getActivity()).removeDataUpdateListener(this);
    super.onDestroyView();
    }

    then anytime the data changes, the fragments all get an update notification:

            for (int i = 0; i < children.length; i++) {
    notifyUpdateListener(i, children[i]);
    }

Note that nowhere in the code is onNotifyDataSetChanged() called on the view pager adapter.

The demo is on GitHub at https://github.com/klarson2/View-Pager-Data-Update


This is what is causing the scrolling:

    @Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}

When you call notifyDataSetChanged(), what the ViewPager does is ask you what to do with the pages it already has.

So it will call getItemPosition to find out: where should this page go? You have three options to respond:

  1. Return an index. So if you return 2 for page 0, then the ViewPager will move the page at 0 to 2.

  2. Return POSITION_UNCHANGED. The page will stay exactly where it is now.

  3. Return POSITION_NONE. This means the page should no longer be displayed.

Once the ViewPager knows where the pages are moved to, it will call getItem() for any gaps in the pages.

So if you don't want the scroll to be disturbed, tell the ViewPager where to put the page instead of telling it to get rid of it and create a new one.



Related Topics



Leave a reply



Submit