如何从 Web 服务将 ViewPager 中的 Fragments 添加到 TabLayout?

How to add Fragments in ViewPager to TabLayout from a web service?

我正在尝试向基于 TabLayout-ViewPager-Fragment 的应用程序添加选项卡 dynamically.The TabLayout 使用自定义视图,在 [=16= 之上有一个 ImageView ].

我现在想要的是根据从 PHP/MySQL 网络服务创建的 JSONArray 中的 JSONObjects 的数量添加选项卡。我在 PagerAdapter 中尝试了下面的方法,但它抛出:

java.lang.IllegalStateException: Can't change tag of fragment TstFrag{df80bc8 #0 id=0x7f080157 android:switcher:2131231063:0}: was android:switcher:2131231063:0 now android:switcher:2131231063:1.

方法如下我的适配器

public class FrgAdapter extends FragmentStatePagerAdapter {
private List<Fragment> mFragmentList = new ArrayList<>();
private List<String> mFragmentTitleList = new ArrayList<>();

public FrgAdapter(FragmentManager fm) {
    super(fm);
}

public FrgAdapter(FragmentManager fm, List<Fragment> mFragmentList, List<String> mFragmentTitleList) {
    super(fm);
    this.mFragmentList = mFragmentList;
    this.mFragmentTitleList = mFragmentTitleList;

}

@Override
public Fragment getItem(int position) {
    return mFragmentList.get(position);
}

@Override
public int getCount() {
    return mFragmentList.size();
}

public void addFragment(Fragment fragment, String title) {
    mFragmentList.add(fragment);
    mFragmentTitleList.add(title);
}

public void insertFromJSONObject(JSONObject jsonObject, Fragment fragment, CircularImageView imageView, TextView textView) throws JSONException {
    JSONArray dataArray = jsonObject.getJSONArray("data");

    for (int i = 0; i < dataArray.length(); i++) {
        JSONObject sectionObj = (JSONObject) dataArray.get(i);

        JSONArray sectionsArray = sectionObj.getJSONArray("section");

        for (int j = 0; j < sectionsArray.length(); j++) {
            JSONObject obj = (JSONObject) sectionsArray.get(j);
            Picasso.get().load(obj.getString("imag")).into(imageView);
            mFragmentList.add(fragment);
            mFragmentTitleList.add(obj.getString("name"));
            textView.setText(obj.getString("name"));
            notifyDataSetChanged();
        }
    }
}

@Override
public CharSequence getPageTitle(int position) {
    return null;
}}

这里是在我的 activity 中调用方法来添加片段的地方:

private void setUpViewPager(ViewPager viewPager, View view) {
    adapter = new FrgAdapter(getSupportFragmentManager());
    /*adapter.addFragment(new MleFrag(), "Men");
    adapter.addFragment(new FmlFrag(), "Women");
    adapter.addFragment(new ChdFrag(), "Children");
    adapter.addFragment(new AceFrag(), "Accessories");
    */
    String url = "https://44091ee6.ngrok.io/Glam/men.json";
    AndroidNetworking.get(url)
            .setPriority(Priority.MEDIUM)
            .build()
            .getAsJSONObject(new JSONObjectRequestListener() {
                @Override
                public void onResponse(JSONObject response) {
                    try {
                        adapter.insertFromJSONObject(response, new TstFrag(), view.findViewById(R.id.circularImageView), view.findViewById(R.id.text_header));
                        adapter.notifyDataSetChanged();
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(ANError anError) {
                    Toast.makeText(getApplicationContext(), anError.toString(), Toast.LENGTH_LONG).show();
                }
            });
    adapter.notifyDataSetChanged();
    viewPager.setAdapter(adapter);
}

这是我的Fragment。在我看来,我想在每次需要时重复使用这个 Fragment

public class TstFrag extends Fragment {

public TstFrag() {

}

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

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    return inflater.inflate(R.layout.layout_cht, container, false);
}}

你可以试试这个:

adapter.insertFromJSONObject(response, view.findViewById(R.id.circularImageView), view.findViewById(R.id.text_header));
adapter.notifyDataSetChanged();

public void insertFromJSONObject(JSONObject jsonObject, CircularImageView imageView, TextView textView) throws JSONException {
    JSONArray dataArray = jsonObject.getJSONArray("data");

    for (int i = 0; i < dataArray.length(); i++) {
        JSONObject sectionObj = (JSONObject) dataArray.get(i);

        JSONArray sectionsArray = sectionObj.getJSONArray("section");

        for (int j = 0; j < sectionsArray.length(); j++) {
            JSONObject obj = (JSONObject) sectionsArray.get(j);

            Picasso.get().load(obj.getString("imag")).into(imageView);
            mFragmentList.add(new TstFrag());
            textView.setText(obj.getString("name"));
            //mFragmentTitleList.add(obj.getString("name"));
            notifyDataSetChanged();
        }
    }
}

这里的基本思想是为 FrgAdapter 的每个条目创建一个新的 TstFrag 实例。

考虑 NOT 手动将片段添加到 viewPager,但只需在 viewPager 适配器上实现 getItem && instantiateItem 方法。然后 viewPager 将控制新 TstFraginstantiation 或只是 重用创建的 之一。 检查此

@Override
public Fragment getItem(final int pos) {
    return TstFrag.getInstance(dataList.get(pos));
}


@NonNull
@Override
public Object instantiateItem(ViewGroup container, int position) {
    Fragment fragment = (Fragment) super.instantiateItem(container, position);
    registeredFragments.put(position, fragment);
    return fragment;
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    registeredFragments.remove(position);
    super.destroyItem(container, position, object);
}

更新

public class DataModel implements Serializable{
  private String name;
  private String image;
  // GETTER && SETTER 
}

替换

private List<String> mFragmentTitleList = new ArrayList<>();

 private List<DataModel> dataList = new ArrayList<>();

insertFromJSONObject

    dataList.clear();
    for (int j = 0; j < sectionsArray.length(); j++) {
        JSONObject obj = (JSONObject) sectionsArray.get(j);
        final DataModel model = new DataModel();
        model.setName(obj.getString("name"));
        model.setImage(obj.getString("imag"));
        // Picasso.get().load(obj.getString("imag")).into(imageView);
        // No need to load image here just fetch for cache if you want.
        Picasso.get().load(model.getImage()).fetch();
        // mFragmentList.add(fragment); // no need handle adding fragment here as mentioned above.
        dataList.add(dataModel);
        // textView.setText(obj.getString("name")); // It's not good to update UI here but update there with fragment on create called mention below.
        // notifyDataSetChanged(); DON'T call this inside the loop but after finish your stuff.
    }
    // Just notify here...
    notifyDataSetChanged();

TstFrag

public class TstFrag extends Fragment {
 private DataModel model;
public TstFrag() {

}

public static TstFrag getInstance(DataModel model){
  TstFrag fragment = new TstFrag();
  Bundle bundle = new Bundle();
  bundle.putSerializable("mData", model);
  fragment.setArguments(bundle);
  return fragment;
} 

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    model = (DataModel)getArguments().getSerializable("mData");
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    final View rootView =  inflater.inflate(R.layout.layout_cht, container, false);
    // findViewById() for imageView and nameTextView 
     Picasso.get().load(model.getImage()).into(imageView);
     nameTextView.setText(model.getName());

}}