2

I have two fragments in my activity (I navigate between them using fragment transaction):

  1. list of subjects
  2. subject detail - list of grades

Subject Fragment layout:

<android.support.v4.widget.SwipeRefreshLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/refresher"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</android.support.v4.widget.SwipeRefreshLayout>

The listener for the swipeRefreshLayout is the activity. It triggers an AsyncTask which downloads new data, notifies fragments that the data has changed and hides the swipeRefreshLayout.

The problematic part of the onPostExecute method:

...

try {
    formatData();
} catch (JSONException e) {
    e.printStackTrace();
}

View refresher = findViewById(R.id.refresher);
((SwipeRefreshLayout) refresher).setRefreshing(false);

marksFragment.notifyUpdate(activity);
subjectsFragment.notifyUpdate(activity);

It normally works, but not in this case:

  • I pull to refresh data
  • I navigate to the subject detail (using fragment transaction)
  • The setRefreshing method is called during the fragment transaction

In this case the subject fragments just hangs there and both fragments are in the activity.

Code of SubjectFragment:

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    ((SwipeRefreshLayout) view.findViewById(R.id.refresher)).setOnRefreshListener((SwipeRefreshLayout.OnRefreshListener) activity);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.subjects_fragment, null);
}

How can I setRefreshing(false) on a refreshLayout and avoid getting the subjects fragment twice?

prompteus
  • 1,051
  • 11
  • 26

3 Answers3

1

I found a similar question on SO:

When switch fragment with SwipeRefreshLayout during refreshing, fragment freezes but actually still work

I use appcompat-v7:23.3.0. This answer worked for me:

This issue seems to still be occurring in appcompat 22.1.1. Wrapping the SwipeRefreshLayout inside a FrameLayout solved this for me.

So my subject fragment layout looks like this:

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v4.widget.SwipeRefreshLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/refresher"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ListView
            android:id="@android:id/list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

    </android.support.v4.widget.SwipeRefreshLayout>
</FrameLayout>
Community
  • 1
  • 1
prompteus
  • 1,051
  • 11
  • 26
0

Change your code,reference answer on stack overflow

  public class YourFragment extends Fragment {
    SwipeRefreshLayout swipeLayout;

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        String[] values = new String[] { "Android List View",
                "Adapter implementation",
                "Simple List View In Android",
                "Create List View Android",
                "Android Example",
                "List View Source Code",
                "List View Array Adapter",
                "Android Example List View",
                "Android List View",
                "Adapter implementation",
                "Simple List View In Android",
                "Create List View Android",
                "Android Example",
                "List View Source Code",
                "List View Array Adapter",
                "Android Example List View",
                "Android List View",
                "Adapter implementation",
                "Simple List View In Android",
                "Create List View Android",
                "Android Example",
                "List View Source Code",
                "List View Array Adapter",
                "Android Example List View"
        };

        final SwipeRefreshLayout swipeView = (SwipeRefreshLayout)view. findViewById(R.id.refresher);

        swipeView.setEnabled(false);
        ListView lView = (ListView) view.findViewById(R.id.your_list_view);
        ArrayAdapter<String> adp = new ArrayAdapter<String>(view.getContext(),
                android.R.layout.simple_list_item_1, android.R.id.text1, values);
        lView.setAdapter(adp);

        swipeView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                swipeView.setRefreshing(true);
                ( new Handler()).postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        swipeView.setRefreshing(false);

                    }
                }, 3000);
            }
        });

        lView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView absListView, int i) {

            }

            @Override
            public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                if (firstVisibleItem == 0)
                    swipeView.setEnabled(true);
                else
                    swipeView.setEnabled(false);
            }
        });

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.subjects_fragment, null);
    }


    }
Community
  • 1
  • 1
Muhammad Waleed
  • 2,517
  • 4
  • 27
  • 75
  • Thanks, I will definitely try it. But why should moving the listener from the activity to the fragment help? – prompteus May 13 '16 at 19:11
  • This doesn't work for me. The problem is that setRefreshing() method forces the fragment to display, even when it's being moved by fragment transaction. Which means: If the setRefreshing method is called while the fragment is being moved out, the fragment gets displayed. Your code calls setRefreshing(false) after 3 seconds, but if navigate to detail fragment in that moment, it's reproducing the same issue. – prompteus May 14 '16 at 09:05
0

I face the same issue my swipelayout.setOnRefresh calls two times.

Basically the reason was not in swipelayout.setOnRefreshLisetener i was loading some data when my recyclerview reaches the end and on swipelayout.setOnRefreshListener i was doing the same.

So what i did to remove the bug is i just commented out the loading method from swipelayout.setOnRefreshListener.

 swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {

                if (mLatestAdapter.getItemCount() > 0) {

                    mLatestAdapter.removeAllItems();
                    mPresenter.resetPagination();
                   // mPresenter.loadMoreItems(false);//commentwed this line 


                }
            }
        });

This is what i was doing in my recyclerview

 mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                // Here get the child count, item count and visibleitems
                // from layout manager

                visibleItemCount = mLayoutManager.getChildCount();
                totalItemCount = mLayoutManager.getItemCount();
                pastVisiblesItems = mLayoutManager
                        .findFirstVisibleItemPosition();
                // Now check if userScrolled is true and also check if
                // the item is end then update recycler view and set
                // userScrolled to false
                if (userScrolled
                        && (visibleItemCount + pastVisiblesItems) == totalItemCount) {
                    userScrolled = false;

                    if (!getBaseActivity().isNetworkConnected()) {
                        getBaseActivity().onError("Internet is not Connected");
                        return;
                    }
                    Log.wtf(TAG, "onScrolled: reach end" );
                    mPresenter.loadMoreItems(true);//here it is after removing all items from recyclerview it calls automatically

                }
            }

            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);

                // If scroll state is touch scroll then set userScrolled
                // true
                if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
                    userScrolled = true;
                }
            }
        });
Nouman Ch
  • 4,023
  • 4
  • 29
  • 42