'Swipe to refresh data using SwipeRefreshLayout in fragment?

I want my layout to be refreshed when the app starts and the data should show in and when the user swipes the data should be updated and show new data if new data is available on the server.

The actual problem is that the data is not loading when the app is started. Rather it is happening only on swiping. How can I achieve that on opening the app the data is loaded first and then the data is updated on swiping?

public class FirstFragment extends Fragment {
    FragmentFirstBinding binding;
    APIInterfaces interfaces;
    ArrayList<VideoModels> list = new ArrayList<>();
    @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        binding = FragmentFirstBinding.inflate(inflater, container, false);
        MyAdapter adapter = new MyAdapter(list,getContext());
        binding.myRecyclerView.setAdapter(adapter);
        GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(),2);
        binding.myRecyclerView.setLayoutManager(gridLayoutManager);
        interfaces = RetrofitInstance.getRetrofit().create(APIInterfaces.class);
        binding.swipeToRefresh.setRefreshing(true);
        binding.swipeToRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                interfaces.getPosts().enqueue(new Callback<List<VideoModels>>() {
                    @SuppressLint("NotifyDataSetChanged")
                    @Override
                    public void onResponse(@NonNull Call<List<VideoModels>> call, @NonNull Response<List<VideoModels>> response) {
                        list.clear();
                        if (response.isSuccessful()) {
                            assert response.body() != null;
                            list.addAll(response.body());
                            adapter.notifyDataSetChanged();
                            binding.swipeToRefresh.setRefreshing(false);
                        }
                    }

                    @Override
                    public void onFailure(@NonNull Call<List<VideoModels>> call, @NonNull Throwable t) {
                        Toast.makeText(getContext(), "Check you Internet", Toast.LENGTH_SHORT).show();
                        binding.swipeToRefresh.setRefreshing(false);
                    }
                });
            }
        });
        binding.swipeToRefresh.setRefreshing(false);

        return binding.getRoot();
    }
}

EDIT-1: Added complete code.

Your answer will helpful for me.



Solution 1:[1]

After finding the solution for 1 day. Finally, I found my solution.

To use SwipeRefreshLayout work in Fragment and want to refresh your data Onswipe. use the below code and modify it as your requirement.

This is a fragment.

public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        binding = FragmentFirstBinding.inflate(inflater, container, false);
        // swiping on starting of an app.
        binding.swipeToRefresh.setRefreshing(true);
        getData();
        binding.swipeToRefresh.setRefreshing(false);

        // when user swipe
        binding.swipeToRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @SuppressLint("NotifyDataSetChanged")
            @Override
            public void onRefresh() {
                getData();
            }
        });
        return binding.getRoot();
    }
    public void getData(){
        // you have to put all of your onCreate code here to work properly. most of time it throws an error. So, make sure you added code properly.
        ArrayList<VideoModels> list = new ArrayList<>();
        MyAdapter adapter = new MyAdapter(list,getContext());
        GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(),2);
        binding.myRecyclerView.setAdapter(adapter);
        binding.myRecyclerView.setLayoutManager(gridLayoutManager);
        binding.swipeToRefresh.setRefreshing(true);
        interfaces = RetrofitInstance.getRetrofit().create(APIInterfaces.class);
        interfaces.getPosts().enqueue(new Callback<List<VideoModels>>() {
            @SuppressLint("NotifyDataSetChanged")
            @Override
            public void onResponse(@NonNull Call<List<VideoModels>> call, @NonNull Response<List<VideoModels>> response) {
                list.clear();
                if (response.isSuccessful()) {
                    assert response.body() != null;
                    list.addAll(response.body());
                    adapter.notifyDataSetChanged();
                    binding.swipeToRefresh.setRefreshing(false);
                }
            }
            @Override
            public void onFailure(@NonNull Call<List<VideoModels>> call, @NonNull Throwable t) {
                Toast.makeText(getContext(), "Check you Internet", Toast.LENGTH_SHORT).show();
                binding.swipeToRefresh.setRefreshing(false);
            }
        });
    }

Solution 2:[2]

You need to call this method in onResume() state

  public void getData() {
            interfaces.getPosts().enqueue(new Callback<List<VideoModels>>() {
                @SuppressLint("NotifyDataSetChanged")
                @Override
                public void onResponse(@NonNull Call<List<VideoModels>> call, @NonNull Response<List<VideoModels>> response) {
                    list.clear();
                    if (response.isSuccessful()) {
                        assert response.body() != null;
                        list.addAll(response.body());
                        adapter.notifyDataSetChanged();
                        binding.swipeToRefresh.setRefreshing(false);
                    }
                }

                @Override
                public void onFailure(@NonNull Call<List<VideoModels>> call, @NonNull Throwable t) {
                    Toast.makeText(getContext(), "Check you Internet", Toast.LENGTH_SHORT).show();
                    binding.swipeToRefresh.setRefreshing(false);
                }
            });
        }

Solution 3:[3]

if you call binding.swipeLayout.isRefreshing = true
in SwipeRefreshLayout source code, mNotify boolean value is false so cannot do anything in setOnRefreshListener

public void onAnimationEnd(Animation animation) {
        if (mRefreshing) {
            // Make sure the progress view is fully visible
            mProgress.setAlpha(MAX_ALPHA);
            mProgress.start();
            if (mNotify) {
                if (mListener != null) {
                    mListener.onRefresh();
                }
            }
            mCurrentTargetOffsetTop = mCircleView.getTop();
        } else {
            reset();
        }
    }

this is why setOnRefreshListener not invoke if you want manual invoke it do like this by reflect set mNotify boolean value is true

val swipeClass = SwipeRefreshLayout::class.java
val method = swipeClass.getDeclaredMethod("setRefreshing", Boolean::class.java, Boolean::class.java)
method.isAccessible = true
method.invoke(binding.swipeLayout, true, true)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 M Dev
Solution 2 Kanzariya Hardik
Solution 3