【问题标题】:Updating only current viewpager fragment仅更新当前的 viewpager 片段
【发布时间】:2020-04-27 14:00:54
【问题描述】:

我有 200 多个标签的 ViewPager。每个选项卡都包含 recyclerview,通过 retrofit2 动态加载数据。每次onTabSelected() 操作后都会加载数据。

但由于 viewpager 加载 position-1 (if any), position, position+1 (if any) 我得到了 2-3 个具有相同数据的标签。

问题是 - 如何只加载当前选择的没有相邻位置的片段?

我认为FragmentPagerAdapter 中的BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT 只需将其传递给构造函数即可解决我的问题:

public Adapter_programmes(FragmentManager fm, Context context) {
    super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
    mContext = context;
    fragment_some = new Fragment_Some();
}

但什么都没有改变。

统一更新: 我想我在这里找到了解决方案:ViewPager offscreen page limit

但我无法理解: 使用占位符图像加载您的网格,并且在页面更改之前不要加载真实图像。

**UPD2:** setOffscreenPageLimit(1) 没有解决我的问题。

我的代码:

片段:

public static Fragment_some newInstance(int page) {
    Bundle args = new Bundle();
    args.putInt(ARG_PAGE, page);
    Fragment_some fragment = new Fragment_some();
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
        mPage = getArguments().getInt(ARG_PAGE);
    }
    arrayNames.clear();
    arrayTimes.clear();
}

@Override
public void onAttach(@NonNull Context context) {
    super.onAttach(context);
    mContext=context;
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    Log.d(TAG, "");
    //creating fragment
    rootView = inflater.inflate(R.layout.content_list, container, false);

    loadProgrammes(CID); //doing retrofit query for data, using argument which I've got from onTabSelected by SharedPreferences
    //data loaded succecfully
    Handler handler = new Handler();
    handler.postDelayed(() -> {
    adapterItem = new Adapter_programme_item(mContext, arrayTimes, arrayNames);
    RecyclerView RV = rootView.findViewById(R.id.recycler_view);
    LinearLayoutManager layoutManager = new LinearLayoutManager(mContext);
    RV.setLayoutManager(layoutManager);
    RV.setAdapter(adapterItem);
            }, 3000);   //3 seconds waiting

    return rootView;
}

FragmentPagerAdapter:

    public Adapter_programmes(FragmentManager fm, Context context) {
    super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
    mContext = context;
    fragment_some = new Fragment_some();
}

@Override public int getCount() {
    return PAGE_COUNT;

}

@Override public Fragment getItem(int position) {


    return fragment_some.newInstance(position + 1);
}

@Override public CharSequence getPageTitle(int position) {
    return tabTitles[position];
}

public void updateTitleData(String[] titles) {
    ...
    notifyDataSetChanged();
}

主活动:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    adapter = new Adapter_programmes(getSupportFragmentManager(), MainActivity.this);

    ViewPager viewPager = findViewById(R.id.viewpager);
    viewPager.setAdapter(adapter);

    TabLayout tabLayout = findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(viewPager);

    loaderFromURL(); //getting tab titles via retrofit

    tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabUnselected(TabLayout.Tab tab) {

        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {

        }

        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            Log.d(TAG, "onTabSelected");

            String mCID = listm3u.get(tab.getPosition()).getItemCID();
            AppPreferences.setCurrentCID(MainActivity.this, mCID);

            String iconURL = listm3u.get(tab.getPosition()).getItemIcon();
            ImageView IVChanelLogo = findViewById(R.id.IVChanelLogo);
            Picasso.with(MainActivity.this).load(iconURL).into(IVChanelLogo);

        }
    });
}

【问题讨论】:

  • 显示更多代码,举例说明每个片段如何加载其数据,因为仅更改该标志可能不会通过更改片段代码为您提供所需的行为。还要指定您使用的 Viewpager 版本。
  • 用我的代码编辑帖子

标签: android android-fragments android-recyclerview android-viewpager android-adapter


【解决方案1】:

因为您正在填充 onCreateView 中的 Fragment 更改为 BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT 的 recyclerview 不会有任何影响。

BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT 不是将当前 Fragment +/- OffscreenPageLimit(默认为 1)带入“Resumed”状态,而是仅将当前 Fragment 带入“Resumed”状态,并将任何其他 Fragment 带入“Started”状态片段生命周期。

由于“已开始”已超过 onCreateView,您的回收站视图已过早填充。

解决方法是在Fragment的onCreateView中创建没有数据的recyclerview适配器,找到recyclerView,设置它的layoutmanger和adapter等。

然后在 Fragment 的 onResume 方法中,为 recyclerView 获取数据并使用此新数据更新 recyclerview 适配器,然后通知 RecyclerView 它的数据已更改。

然后您可以删除 onTabSelected 的东西

没有足够的示例代码来给出一个工作示例,但下面是一个示例片段,它显示了 textview2 的更新与“恢复”时的当前时间相比,textview1 在它被带到“时设置”已开始”状态(您将在 Viewpager 中创建此片段的 3 个副本并设置 BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT

package com.test.viewpager;

import android.content.Context;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;

public class TextFragment extends Fragment {
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";

    private int mParam1;
    private View view;


    public TextFragment() {
        // Required empty public constructor
    }

    public static TextFragment newInstance(int param1) {
        TextFragment fragment = new TextFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_PARAM1, param1);
        fragment.setArguments(args);
        Log.d("Frag", "newInstance");
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getInt(ARG_PARAM1);
        }
        Log.d("Frag", "onCreate");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        Log.d("Frag", "onCreateView:" + mParam1);
        view = inflater.inflate(R.layout.fragment_text, container, false);

        return view;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        Log.d("Frag", "onViewCreated:" + mParam1);
        Bundle args = getArguments();
        TextView textView1 = view.findViewById(R.id.textview1);
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH-mm-ss.sss", Locale.US);
        String dt = df.format(Calendar.getInstance().getTime());
        textView1.setText(dt);
    }


    public void updateView(){
        Log.d("Frag", "updateView");
        TextView textView2 = view.findViewById(R.id.textview2);
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH-mm-ss.sss", Locale.US);
        String dt = df.format(Calendar.getInstance().getTime());
        textView2.setText(dt);
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        Log.d("Frag", "onAttach:" + mParam1);
    }

    @Override
    public void onDetach() {
        super.onDetach();
        Log.d("Frag", "onDetach:" + mParam1);
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d("Frag", "onResume:" + mParam1);
        updateView();
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.d("Frag", "onPause:" + mParam1);
    }
}


【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多