4

I am trying to make a layout with recyclerview something like the video. I made a recyclerview which update list after certain interval but the problem is after data update it scroll to top position automatically. I want to make something like the video. https://youtu.be/omcS-6LeKoo I have tried with link from SO RecyclerView scrolls to top position when change the adapter data RecyclerView notifyDataSetChanged scrolls to top position but unable to solve. below is my attempt

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

        recyclerView = findViewById(R.id.recyclerViewId);

        handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
//                Toast.makeText(getApplicationContext(),"Updating",Toast.LENGTH_LONG).show();
                listShow();
                handler.postDelayed(this,1000);

            }
        },1000);

    }

void listShow(){

        retrofitApiCall = RetrofitInstance.getRetrofitInstance().create(RetrofitApiCall.class);
        Call<ModelClass_JSONParse> getDetails = retrofitApiCall;
        anime = ExtendedAnime.getAll();

        getDetails.enqueue(new Callback<ModelClass_JSONParse>() {
            @Override
            public void onResponse(Call<ModelClass_JSONParse> call, 
         Response<ModelClass_JSONParse> response) {
                Log.v("Res",response.toString());
                getWithValues = new HashMap<>();

                if (response.isSuccessful()){

                        list.add(mModelClass_adapter);
                    }
                    adapter = new Adapter(getApplicationContext(),list);
                    StaggeredGridLayoutManager layoutManager = new 
                    StaggeredGridLayoutManager(1,StaggeredGridLayoutManager.VERTICAL);
                    recyclerView.setLayoutManager(layoutManager);
                    recyclerView.setAdapter(adapter);
                    adapter.notifyDataSetChanged();

                }
            }

            @Override
            public void onFailure(Call<ModelClass_JSONParse> call, Throwable t) {
                Log.v("Res",call.toString());
            }
        });
    }
AAA
  • 475
  • 6
  • 21

6 Answers6

1

The problem is probably because of you are setting new adapter reference in network callback method onResponse(). Try setting adapter in onCreate and then update dataset in callback.

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    recyclerView = findViewById(R.id.recyclerViewId);
    recyclerView.setAdapter(yourAdapter);
}

In network callback,

@Override
        public void onResponse(Call<ModelClass_JSONParse> call, 
     Response<ModelClass_JSONParse> response) {
            Log.v("Res",response.toString());
            getWithValues = new HashMap<>();

            if (response.isSuccessful()){

                adapter.setDataSet(newDataList) //not change adapter reference,only update data set  

            }
        }

Implement setDataSet() method in your adapter to update list like below.

class YourAdapter extends RecyclerView.Adapter<>{
      priavate List<> list = new ArrayList();

      public void setDataSet(newList:List<>){ 
          list.clear();
          list.addAll(newList);
          notifyDataSetChanged();
      }
}
Chan Myae Aung
  • 487
  • 3
  • 13
  • let me time to give a try – AAA Nov 14 '19 at 05:47
  • or if you still want to stick to a position just get that position and call this before notifying adapter `recyclerView.scrollToPosition(pos);` //use to focus the item with index `adapter.notifyDataSetChanged();` – animusmind Nov 14 '19 at 06:13
  • your ans did not work too. list not showing up either. – AAA Nov 14 '19 at 06:15
0

Don't use adapter.notifyDataSetChanged(); method because I think your main view must be wrap content so either set a fixed height like 150dp.

Try different methods like notifyItemChanged(), notifyItemRangeChanged(), notifyItemInserted()

Venky
  • 1,440
  • 4
  • 13
  • 24
0

You are setting adapter again and again when the response is changing, so you should change list and set adapter in onCreate.

Arraylist<ModelClass_adapter> list =  new Arraylist<ModelClass_adapter>;
Adapter adapter;
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView = findViewById(R.id.recyclerViewId);

        //set adapter here
        adapter = new Adapter(getApplicationContext(),list);
                    StaggeredGridLayoutManager layoutManager = new 
                    StaggeredGridLayoutManager(1,StaggeredGridLayoutManager.VERTICAL);
                    recyclerView.setLayoutManager(layoutManager);
                    recyclerView.setAdapter(adapter);

        handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
//                Toast.makeText(getApplicationContext(),"Updating",Toast.LENGTH_LONG).show();
                listShow();
                handler.postDelayed(this,1000);

            }
        },1000);

    }

void listShow(){

        retrofitApiCall = RetrofitInstance.getRetrofitInstance().create(RetrofitApiCall.class);
        Call<ModelClass_JSONParse> getDetails = retrofitApiCall;
        anime = ExtendedAnime.getAll();

        getDetails.enqueue(new Callback<ModelClass_JSONParse>() {
            @Override
            public void onResponse(Call<ModelClass_JSONParse> call, 
         Response<ModelClass_JSONParse> response) {
                Log.v("Res",response.toString());
                getWithValues = new HashMap<>();

                if (response.isSuccessful()){
                        list.clear();
                        list.add(mModelClass_adapter);
                    }

                    adapter.notifyDataSetChanged();

                }
            }

            @Override
            public void onFailure(Call<CurrencyModelClass_JSONParse> call, Throwable t) {
                Log.v("Res",call.toString());
            }
        });
    }
Chetan Shelake
  • 525
  • 4
  • 13
0

These lines of code are causing the problem for you. You're setting a new adapter reference and linear layout manager reference every time of your API calling.

                            adapter = new Adapter(getApplicationContext(),list);
                            StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(1,StaggeredGridLayoutManager.VERTICAL);
                            recyclerView.setLayoutManager(layoutManager);
                            recyclerView.setAdapter(adapter);

To Do your desired task you need to do following steps -

  1. Just set your LayoutManager and adapter for the first time.
  2. Make a setDataList method in your adapter class. And set your updated list to adapter list.
  3. And then every time of calling API set that list to setDataList and call adapter.notifyDataSetChanged() method of your adapter class.

The above steps will solve your problem. Just give it a try.

Al-Amin
  • 1,016
  • 7
  • 21
0

You are setting a new adapter every time and a new layout manager response comes. which may cause this type of problem. you need to set adapter and layout manager in onCreate. just update adapter list in response of the api.

according to this answer you need linear layout manager only.

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

    recyclerView = findViewById(R.id.recyclerViewId);
    list= ArrayList<>();
    adapter = new Adapter(getApplicationContext(),list);
    LinearLayoutManager linearLayoutManager = new 
                LinearLayoutManager(context, OrientationHelper.VERTICAL, false);
    recycleView.setLayoutManager(linearLayoutManager);
    recyclerView.setAdapter(adapter);
    handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
//                Toast.makeText(getApplicationContext(),"Updating",Toast.LENGTH_LONG).show();
            listShow();
            handler.postDelayed(this,1000);

        }
    },1000);

}

void listShow(){

    retrofitApiCall = RetrofitInstance.getRetrofitInstance().create(RetrofitApiCall.class);
    Call<ModelClass_JSONParse> getDetails = retrofitApiCall;
    anime = ExtendedAnime.getAll();

    getDetails.enqueue(new Callback<ModelClass_JSONParse>() {
        @Override
        public void onResponse(Call<ModelClass_JSONParse> call, 
     Response<ModelClass_JSONParse> response) {
            Log.v("Res",response.toString());
            getWithValues = new HashMap<>();

            if (response.isSuccessful()){

                    adapter.getList().add(mModelClass_adapter);
                }

                adapter.notifyDataSetChanged();

            }
        }

        @Override
        public void onFailure(Call<CurrencyModelClass_JSONParse> call, Throwable t) {
            Log.v("Res",call.toString());
        }
    });
}
Amit Goswami
  • 174
  • 10
0

you can do by following way

First get the count of your current datalist

int position = datalist.size();

after adding data into datalist call DataAdapter.notifyDataSetChanged();

then move cursor to position in recyclerview recyclerView.scrollToPosition(position);

Happy coding...!