Android
SwipeRefreshLayout

SwipeRefreshLayoutをListFragmentで使うとゾンビ化することがある

More than 3 years have passed since last update.

事例

  1. SwipeRefreshLayoutを使おうと思った時に、既存のクラス(ListFragmentを継承)をあまり変更したくなかったので、SwipeRefreshListFragmentという新しいクラスを作成し、それを継承する形に

  2. SwipeRefreshListFragmentのコードはここのコードをそのまま使用

  3. Refreshしている最中に別のFragmentへ遷移しようとすると遷移前の画面が残ってしまう(裏ではきちんと遷移先のFragmentの処理が走っている)

  4. HierarchyViewerを見ても残っているレイアウトが見当たらない(まるでゾンビ)

試したこと

  • SwipeRefreshListFragmentonPauseの中でsetRefresh(false)

    • 効果なし
  • SwipeRefreshListFragmentのコード内にあるような、SwipeRefreshLayoutをコード上から生成するのをやめ、XMLから生成するように

    • 効果なし

解決策

SwipeRefreshLayoutの外側にFrameLayoutを設置する

  • SwipeRefreshListFragment.ListFragmentSwipeRefreshLayoutを別のjavaファイルに分割する
    • 以下のようなクラスを作る
ListFragmentSwipeRefreshLayout.java
public class ListFragmentSwipeRefreshLayout extends SwipeRefreshLayout {

    public ListFragmentSwipeRefreshLayout(Context context) {
        super(context);
    }

    public ListFragmentSwipeRefreshLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean canChildScrollUp() {
        ListView listView = (ListView) findViewById(android.R.id.list);
        return listView.getVisibility() == View.VISIBLE && ViewCompat.canScrollVertically(listView, -1);
    }
}
  • res/layout/fragment_swipe_refresh.xmlを作る
fragment_swipe_refresh.xml
<?xml version="1.0" ?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
        >

    <com.example.ListFragmentSwipeRefreshLayout
            android:id="@+id/swipe_list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            >

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

    </com.example.ListFragmentSwipeRefreshLayout>
</FrameLayout>
  • SwipeRefreshListFragmentonCreateViewを以下のように変更する
SwipeRefreshListFragment.java
 @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View listFragmentView = inflater.inflate(R.layout.fragmetn_swipe_refresh, container, false);
        mSwipeRefreshLayout = (SwipeRefreshLayout) listFragmentView.findViewById(R.id.swipe_list);
        return listFragmentView;
    }

参考

https://code.google.com/p/android/issues/detail?id=78062
http://stackoverflow.com/questions/27057449/when-switch-fragment-with-swiperefreshlayout-during-refreshing-fragment-freezes/27073879#27073879