I have a Fragment
with a SwipeRefreshLayout
and then RecyclerView
as child.
When the Fragment is committed, it starts talking to a server in order to retrieve some data and populate a CustomAdapter which will serve the RecyclerView.
The user can refresh the content by swiping down or pressing a button on the ActionBar. In the latter case, I manually call swipeRefreshLayout.setRefreshing(true)
. So no troubles until now.
The problem arises when I manually call the refresh state during the first loading of the RecyclerView (onStart()
).
The progress indicator is not showed up and I assume because the RecyclerView is still empty since it requires some seconds to retrieve all the data...
I leave you some code.
Fragment code:
public class MyFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View mView = inflater.inflate(R.layout.fragment_stop, container, false);
mRecyclerView = (RecyclerView) mView.findViewById(R.id.recyclerView1);
mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(),
DividerItemDecoration.VERTICAL_LIST));
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//SwipeRefreshLayout retrieved and configured
swipeLayout = (SwipeRefreshLayout) mView.findViewById(R.id.swipe_container);
swipeLayout.setOnRefreshListener(this);
swipeLayout.setColorSchemeResources(
R.color.primaryColor,
R.color.cyan_500,
R.color.light_green_500,
R.color.amber_500);
return mView;
}
...
@Override
public void onStart() {
super.onStart();
executeSchedule(); //First execution and data loading.
}
...
@Override
public void onRefresh() {
executeSchedule();
}
...
public void executeSchedule() {
new Schedule().execute();
}
private class Schedule extends AsyncTask<Void, Void, Void> {
...
@Override
protected void onPreExecute() {
super.onPreExecute();
if(!swipeLayout.isRefreshing()) {
swipeLayout.setRefreshing(true); //set refresh state
}
}
@Override
protected Void doInBackground(Void... params) {
...
}
@Override
protected void onPostExecute(Void result) {
adap = new CustomAdapter(getActivity(), ...);
mRecyclerView.setAdapter(adap);
swipeLayout.setRefreshing(false);
}
}
XML code:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/section_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:paddingBottom="2dp"
android:layout_marginTop="5dp"
android:divider="#e0e0e0"
tools:context=".MyFragment" />
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
</FrameLayout>
What would be the best practice to address this situation? Adding a second dummy SwipeRefreshLayout? Immediately force an empty adapter?
You need to call measure method before call setRefreshing(true)
.
Take a look at: SwipeRefreshLayout no animation on fragment creation. Maybe it can be helpful.