Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

recyclerview add data to the top without mess up scroll?

I'm trying to add some date on scroll top in a recyclerview. it is work, except the scroll, it mess everything up when some new data is added.

I saw this topics:

Link 1

Link 2

but none of them solved my problem.

maybe someone can help me with this...

I get some data using volley, like so:

try {
                //Getting json
                json = array.getJSONObject(i);

                //Adding data to the object
                PostObj.setImageUrl(json.getString(Config.TAG_PPIC));
                ...


            } catch (JSONException e) {
                e.printStackTrace();
            }
            //Adding object to the list
            listLf.add(0, PostObj); //0, postobj
        }

        //Notifying the adapter that data has been added or changed
        //adapter.notifyDataSetChanged(); the scroll will jump to position 0
        adapter.notifyItemRangeChanged(0, adapter.getItemCount()); // still not working
    }

I tried to add adapter.notifyItemRangeChanged(0, adapter.getItemCount()); but still the same thing.

also I tried:

// Save state
private Parcelable recyclerViewState;
recyclerViewState = recyclerView.getLayoutManager().onSaveInstanceState();

// Restore state
recyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);

and it doesn't work too. maybe I place it in the wrong place or something...

I want some suggestions what I'm doing wrong and how can I get the new data, notify the adapter without mess the scroll position?


edit---------------------------------- full class:

public class Comments extends BaseActivity {


    private List<LfGetSet> listLf;

    //Creating Views
    private RecyclerView recyclerView;
    private RecyclerView.LayoutManager layoutManager;
    private RecyclerView.Adapter adapter;

    //Volley Request Queue
    private RequestQueue requestQueue;
    private String requestCount = "0";
    private String lastrequestCount = "0";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ViewGroup content = (ViewGroup) findViewById(R.id.content_frame);
        getLayoutInflater().inflate(R.layout.activity_comments, content, true);

        //Initializing Views
        recyclerView = (RecyclerView) findViewById(R.id.recyclerViewLf);
        recyclerView.setHasFixedSize(true);
        //layoutManager = new LinearLayoutManager(this);

        final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setStackFromEnd(true);

        recyclerView.setLayoutManager(layoutManager);

        //Initializing our list
        listLf = new ArrayList<>();
        requestQueue = Volley.newRequestQueue(this);

        //Calling method to get data to fetch data
        getData();

        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                if (isLastItemDisplaying(recyclerView)) {
                    getData();
                }
            }
        });

        //initializing our adapter
        adapter = new LfAdapter(listLf, this);

        //Adding adapter to recyclerview
        recyclerView.setAdapter(adapter);


    }

    private JsonArrayRequest getDataFromServer(String requestCount) {
        ...
        return jsonArrayRequest;
    }

    //This method will get data from the web api
    private void getData() {
        //Adding the method to the queue by calling the method getDataFromServer
        requestQueue.add(getDataFromServer(requestCount));
        lastrequestCount = requestCount;
        //Incrementing the request counter
        requestCount++;
    }

    //This method will parse json data
    private void parseData(JSONArray array) {
        for (int i = 0; i < array.length(); i++) {
            //Creating the object
            LfGetSet PostObj = new LfGetSet();
            JSONObject json = null;
            try {
                //Getting json
                json = array.getJSONObject(i);

                //Adding data to the object
                PostObj.setImageUrl(json.getString(Config.TAG_PPIC));
                ...


            } catch (JSONException e) {
                e.printStackTrace();
            }
            //Adding object to the list
            listLf.add(0, PostObj); //0, postobj
        }

        //Notifying the adapter that data has been added or changed
        adapter.notifyDataSetChanged();
    }

    //This method would check that the recyclerview scroll has reached the bottom or not
    private boolean isLastItemDisplaying(RecyclerView recyclerView) {
        if (recyclerView.getAdapter().getItemCount() != 0) {
            int lastVisibleItemPosition = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition();
            if (lastVisibleItemPosition != RecyclerView.NO_POSITION
                    && lastVisibleItemPosition == 1
                    && lastrequestCount != requestCount
                    && requestCount != "0")
                return true;
        }
        return false;
    }

}
like image 925
Gabriela Dias Avatar asked Nov 08 '22 00:11

Gabriela Dias


1 Answers

You can try this approach where you add a new item to the list as per normal and then update the data in the array and put the new one at the top.

   // Add a new item the usual way so it goes at the bottom

    int x = 0;

   // Create a new Data list. New item goes 1st

   // Create a Loop

    myList.remove(x); // Remove item from the array at position

    MyList myList = new MyList();

    myList.add(x, theData); // Add data to array at position


    // Now that new data has been inserted to the Array at position X update the List item at that same Position. I usually do this in the Background.

    Handler handler = new Handler();

    final int finalX = x;
    final Runnable r = new Runnable() {
        public void run() {
            adapter.notifyItemChanged(finalX);  // Notify Adapter that the Items data has changed and Update
        }
    };

    handler.post(r);

    x++;

Code that reads updated data from the DB and then updates List items on the fly with that new data. But in your case you need to add 1 new item and update the List with the new items data at position 0 in the array and on the List. Old items get their position shifted by 1.

public void updateStocks() {

        System.out.println("Updating");
        int rec = db.getRecordsCount() - 1;

        List<Records> record = db.getAllRecords();

        int x = 0;

        for (Records cn : record) {

            stocksList.remove(x);

            Livestocks stocks = new Livestocks();

            stocks.setID(cn.getID());
            stocks.setName(cn.getName());
            stocks.setTicker(cn.getTicker());
            stocks.setPrice(cn.getPrice());
            stocks.setOpen(cn.getOpen());
            stocks.setChange(cn.getChange());
            stocks.setPchange(cn.getPchange());
            stocks.setDhigh(cn.getDhigh());
            stocks.setDlow(cn.getDlow());
            stocks.setYhigh(cn.getYhigh());
            stocks.setYlow(cn.getYlow());
            stocks.setVol(cn.getVol());
            stocks.setShares(cn.getShares());
            stocks.setIown(cn.getIown());
            stocks.setMcap(cn.getMcap());
            stocks.setStatus(cn.getStatus());
            stocks.setExchange(cn.getExchange());

            stocksList.add(x, stocks);

            Handler handler = new Handler();

            final int finalX = x;
            final Runnable r = new Runnable() {
                public void run() {
                    adapter.notifyItemChanged(finalX);
                }
            };

            handler.post(r);

            x++;

            if (rec == x) {
            //do nothing
            }
        }

    }
like image 103
Tasos Avatar answered Nov 14 '22 22:11

Tasos