'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 |