天天看點

ViewPager+Fragment解決懶加載多次請求資料問題以及Fragment渲染完畢後在請求的方案

解決問題:

1.ViewPager的懶加載模式為了讓切換更加流暢,但是會多預加載的Fragment需要的資料進行網絡請求,當多個Fragment都存在大量資料的時候,容易因為隊列中請求較多導緻卡頓,也浪費流量。

2.頻繁切換ViewPager造成過多的網絡請求。

3.在UI還沒有渲染完成的時候請求資料,導緻空指針異常。

解決方案:抽象基類的建立

public abstract class BasePageFragment extends Fragment {
    protected boolean isViewInitiated;
    protected boolean isVisibleToUser;
    protected boolean isDataInitiated;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        isViewInitiated = true;
        prepareFetchData();
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        this.isVisibleToUser = isVisibleToUser;
        prepareFetchData();
    }

    public abstract void fetchData();

    public boolean prepareFetchData() {
        return prepareFetchData(false);
    }

    public boolean prepareFetchData(boolean forceUpdate) {
        if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) {
            fetchData();
            isDataInitiated = true;
            return true;
        }
        return false;
    }
}
           

看代碼這裡隻有一個setUserVisibleHint需要說下,此方法用于判斷Fragment上面的UI是否已經可視了,是以在prepareFetchData方法裡我們做如下判斷:就是目前UI可見,并且fragment已經初始化完畢,如果網絡資料未加載,那麼請求資料。由于我們選用的是

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/recyclerview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerVertical="true"
    android:scrollbars="none">

</android.support.v7.widget.RecyclerView>
           

此插件有下拉重新整理的回調方法,是以當你主觀需要重新整理的時候可以直接下拉重新整理資料,就不要每一次切換頁面都發起請求了。

接下裡就是ViewPager中的Fragment隻需要繼承改抽象類,實作

fetchData() 方法即可:      
@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
public class Item1Fragment extends BasePageFragment {

    private XRecyclerView xRecyclerView;
    private ItemAdapter adapter = null;

    private List<TaskDetail> lists;

    public Item1Fragment() {
    }


    @Override
    public void fetchData() {
        ApiServiceUnified.getOurInstance().getTaskList("23442704051802179';", "0",
                null,
                null,
                new retrofit2.Callback<ResponseUnified60001>() {
                    @Override
                    public void onResponse(Call<ResponseUnified60001> call, Response<ResponseUnified60001> response) {

                    }

                    @Override
                    public void onFailure(Call<ResponseUnified60001> call, Throwable throwable) {

                    }
                });
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_item1,null);
        xRecyclerView = view.findViewById(R.id.recyclerview);
        xRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
        initData();


        adapter = new ItemAdapter(getContext(),lists);
        xRecyclerView.setAdapter(adapter);

        adapter.setOnClickItemListener(new ItemAdapter.OnClickItemListener() {
            @Override
            public void onClick(TaskDetail taskDetail) {
                Intent intent = new Intent(getActivity(), TaskDetailsActivity.class);
                switch (taskDetail.getType()){
                    case "1"://待派件
                        break;
                    case "2"://待回收
                        break;
                    case "3"://代送回執包
                        break;
                }
                startActivity(intent);
            }
        });

        return view;
    }
}
           

可以實作的效果,就是隻有當Fragment渲染完成才發起請求,切在預加載的頁面中,請求過的頁面不會再第二次發起請求,如果需要就下拉重新整理。