关于加载数据的 TabLayout 问题

Issue on TabLayout regarding load data

我在 android 方面没有经验,我为 Tablayout 实现了代码,其中我有六个选项卡,每个选项卡都有 ListView,其中数据将来自服务器。我正在使用 VolleyResponse 来获取数据,但所有选项卡的数据都是在打开时提供的。我需要数据应该在滑动时出现,当用户去之前的滑动数据不应该再次加载。所以请指导我该怎么办? 下面是我的片段代码。

   private void setupViewPager(ViewPager viewPager) {
    int numberOfPages=7;
    ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
    adapter.addFragment(new Matches_Tab(), "Matches");
    adapter.addFragment(new NewMatches_Tab(), "New matches");
    adapter.addFragment(new Similar_Matchs_Tab(), "Similar Matches");
    adapter.addFragment(new ShortlistTab(), "ShortListed");
    adapter.addFragment(new Viewed_My_Profile(), "View My Profile");
    adapter.addFragment(new ShortListedMeTab(), "ShortListed Me");
    adapter.addFragment(new Photo_Request_Received(), "Photo Request Received");
    viewPager.setOffscreenPageLimit(numberOfPages);
    viewPager.setAdapter(adapter);
}

片段class

public class Matches_Tab extends Fragment{
// Session Manager Class
SessionManager session;
String email;
public String JSON_URL;
private ListView listView;
public Matches_Tab() {}


private static Matches_Tab instance;

public static synchronized Matches_Tab getInstance(Bundle data){
    if (instance == null) {
        instance = new Matches_Tab();
        instance.setArguments(data);
    }
    return instance;
}

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

    TypefaceUtil.overrideFont(getContext(), "SERIF", "Peddana-Regular.ttf");

    // Session class instance
    session = new SessionManager(getActivity());
    // get user data from session
    HashMap<String, String> user = session.getUserDetails();
    email = user.get(SessionManager.KEY_EMAIL);
    JSON_URL = "https://www.maangal.com/maangal_mobile/matches.php?matri_id="+email;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view= inflater.inflate(R.layout.matches_tab, container, false);
  //  ProgressBar progressbar = (ProgressBar) view.findViewById(R.id.progressBar);
    listView = (ListView) view.findViewById(R.id.listView);
    sendRequest();
    //getArguments();
    return view;
}


private void sendRequest(){
    final ProgressDialog loading = ProgressDialog.show(getActivity(),"Loading Data", "Please wait...",false,false);

    StringRequest stringRequest = new StringRequest(Request.Method.POST,JSON_URL,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    loading.dismiss();
                    showJSON(response);
                    Log.e("Broder Matches s----->",response);
                          }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Toast.makeText(getContext(),error.getMessage(), Toast.LENGTH_LONG).show();
                }
            });
    int MY_SOCKET_TIMEOUT_MS = 30000;
    stringRequest.setRetryPolicy(new DefaultRetryPolicy(
            MY_SOCKET_TIMEOUT_MS, DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
            DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));

    RequestQueue requestQueue = Volley.newRequestQueue(getContext());
    requestQueue.add(stringRequest);
}

protected void showJSON(String json){
    ParseJSON pj = new ParseJSON(json);
    pj.parseJSON();
    Profile_Match_custom_List cl = new Profile_Match_custom_List(getActivity(), ParseJSON.ids,ParseJSON.ages, ParseJSON.heights, ParseJSON.communities,ParseJSON.castes,ParseJSON.educations,ParseJSON.occupations,ParseJSON.incomes,ParseJSON.pics,ParseJSON.locations,ParseJSON.shortlist,ParseJSON.expressinterest);
    listView.setAdapter(cl);
  }
}

您可以扩展 BaseFragment

public abstract class BaseFragment extends Fragment {

protected Activity mActivity;

/**
 * isFragmentVisible
 */
private boolean isFragmentVisible;
/**
 * View in onCreateView is ok
 */
private boolean isPrepared;
/**
 * isFirstLoad
 */
private boolean isFirstLoad = true;
/**
 * isForceLoad
 */
private boolean isForceLoad = false;


/**
 * onAttach Activity
 *
 * @param context
 */
@Override
public void onAttach(Context context) {
    super.onAttach(context);
    this.mActivity = (Activity) context;
}


@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container
        , Bundle savedInstanceState) {

    isFirstLoad = true;
    View view = LayoutInflater.from(mActivity)
            .inflate(getLayoutId(), container, false);
    initView(view, savedInstanceState);
    isPrepared = true;
    lazyLoad();

    return view;
}

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

@Override
public void onDestroy() {
    super.onDestroy();
}


/**
 * want to load data ,need set in onCreateView
 * isPrepared = true;
 */
protected void lazyLoad() {
    if (isPrepared() && isFragmentVisible()) {
        if (isForceLoad || isFirstLoad()) {
            isForceLoad = false;
            isFirstLoad = false;
            initData();
        }
    }
}

public boolean isPrepared() {
    return isPrepared;
}

public boolean isFirstLoad() {
    return isFirstLoad;
}

public boolean isFragmentVisible() {
    return isFragmentVisible;
}

/**
 * use with viewpager
 *
 * @param isVisibleToUser is visible for user
 */
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (getUserVisibleHint()) {
        onVisible();
    } else {
        onInvisible();
    }
}

/**
 * if you use show hide to set fragment ,do this
 *
 * @param hidden hidden True if the fragment is now hidden, false if it is not
 *               visible.
 */
@Override
public void onHiddenChanged(boolean hidden) {
    super.onHiddenChanged(hidden);
    if (!hidden) {
        onVisible();
    } else {
        onInvisible();
    }
}

protected void onVisible() {
    isFragmentVisible = true;
    lazyLoad();
}

protected void onInvisible() {
    isFragmentVisible = false;
}

/**
 * set force load
 */
public void setForceLoad(boolean forceLoad) {
    this.isForceLoad = forceLoad;
}


/**
 * getLayoutId ,like : R.layout.fragment
 *
 * @return
 */
protected abstract int getLayoutId();

/**
 * initView
 *
 * @param view
 * @param savedInstanceState
 */
protected abstract void initView(View view, Bundle savedInstanceState);

/**
 * load data here
 */
protected abstract void initData();

}

然后在initData方法中加载数据。

@Override
protected void initData() {
   // request here
}

备注

  • 主要方法是setUserVisibleHintonHiddenChanged
  • 添加一些布尔标志以确定数据是否已加载、视图是否已创建等

您可以使用 ViewPager.OnPageChangeListener 获取页面变为可见时的回调。 检查下面的代码。

viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
    @Override
    public void onPageSelected(int position) {
        // Add your logic
    } 
});

如果您正在使用 ViewPager 并且您在一个 API 调用中获取所有选项卡的数据,那么我建议您将 viewpager 的偏移量设置为等于选项卡的数量。

ViewPager vp = ...;
vp.setOffscreenPageLimit(numberOfTabsHERE);

注意:仅当没有太多数据可显示时才使用此选项,否则您可能会得到 MemoryOutOfException.

如果您确实有很多选项卡和大量数据。对片段使用 Singleton 模式是一个不错的选择。

public class MyFragment extends Fragment {
    private static MyFragment instance;

    public static synchronized MyFragment getInstance(Bundle data // if any){
        if (instance == null) {
            instance = new MyFragment();
            instance.setArguments(data);
        }
        return instance;
    }
}
...
onCreateView{.... getArguments()}

备用解决方案

tabLayout.setupWithViewPager(mViewPager);
tabLayout.setOnTabSelectedListener(
  new TabLayout.ViewPagerOnTabSelectedListener(mViewPager) {
    @Override
    public void onTabSelected(TabLayout.Tab tab) {
        super.onTabSelected(tab);
        //put your Logic here
    }
});