android 中的 ViewPager + RecyclerView 问题
ViewPager + RecyclerView issue in android
您好,我有 Tablayout
和 Viewpager
,我正在使用 Fragment
作为 tablayout。现在在每个 Tablayout 片段中我都有 Recyclerview
并显示 items.Please 看到这个我的 json 响应
在 "typeMaster" 中:数组我有类别 "typeName":"Dogs",我在 tablayout 中显示类型名称我有 4 个 tablayout,在 typemaster 中我有子类别名为 "catMaster":我正在尝试在 recyclerview 中显示 catmaster 数据,但问题出在它显示最后数据的每个片段中 "catName":"Vitamins & Minerals",
Activity
public class CategoriesActivity extends AppCompatActivity{
private Header myview;
private ArrayList<SubcategoryModel> subct;
private ArrayList<CategoryModel> filelist;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.categoris_activity);
filelist = (ArrayList<CategoryModel>)getIntent().getSerializableExtra("categorylist");
System.out.println("Category list size"+filelist.size());
myview = (Header) findViewById(R.id.categorisactivity_headerView);
myview.setActivity(this);
TabLayout tabLayout = (TabLayout) findViewById(R.id.cat_tab_layout);
for(int i = 0; i < filelist.size(); i++){
subct=filelist.get(i).getItems();
for(int j=0;j<subct.size();j++)
{
}
System.out.println("SubCategory list size"+subct.size());
}
for(int i = 0; i < filelist.size(); i++){
tabLayout.addTab(tabLayout.newTab().setText(filelist.get(i).getCategory_typename()));
ArrayList<SubcategoryModel> subct=filelist.get(i).getItems();
for(int j=0;j<subct.size();j++)
{
}
}
Bundle bundleObject = new Bundle();
bundleObject.putSerializable("key", filelist);
FirstFragment ff=new FirstFragment();
ff.setArguments(bundleObject);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
final ViewPager viewPager = (ViewPager) findViewById(R.id.categories_pager);
CategoriesAdapter mPagerAdapter = new CategoriesAdapter(getSupportFragmentManager(),tabLayout.getTabCount());
viewPager.setAdapter(mPagerAdapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
public class CategoriesAdapter extends FragmentStatePagerAdapter {
ArrayList<CategoryModel> catlist;
int numoftabs;
public CategoriesAdapter(FragmentManager fm, int numoftabs) {
super(fm);
this.numoftabs = numoftabs;
}
@Override
public Fragment getItem(int position) {
Log.v("adapter", "getitem" + String.valueOf(position)+subct.size());
return FirstFragment.create(position,subct);
}
@Override
public int getCount() {
return numoftabs;
}
}
}
片段
public class FirstFragment extends Fragment {
// Store instance variables
public static final String ARG_PAGE = "page";
private int mPageNumber;
private Context mContext;
private int Cimage;
private ArrayList<SubcategoryModel> subcatlist;
private RecyclerView rcylervw;
private ArrayList<CategoryModel> filelist;
ArrayList<SubcategoryModel> subct;
public static FirstFragment create(int pageNumber,ArrayList<SubcategoryModel> subct){
FirstFragment fragment = new FirstFragment();
Bundle args = new Bundle();
args.putInt(ARG_PAGE, pageNumber);
args.putSerializable("key", subct);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPageNumber = getArguments().getInt(ARG_PAGE);
subct= (ArrayList<SubcategoryModel>) getArguments().getSerializable("key");
System.out.println("Frag Category list size"+subct.size());
/* for(int i = 0; i < filelist.size(); i++){
subct=filelist.get(i).getItems();
for(int j=0;j<subct.size();j++)
{
}
System.out.println("Frag SubCategory list size"+subct.size());
}*/
// image uri get uri of image that saved in directory of app
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater
.inflate(R.layout.test, container, false);
rcylervw=(RecyclerView)rootView.findViewById(R.id.subcategory_recycler_view);
rcylervw.setHasFixedSize(true);
MyAdapter adapter = new MyAdapter(subct);
rcylervw.setAdapter(adapter);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rcylervw.setLayoutManager(llm);
return rootView;
}
// this method is not very important
}
我的适配器
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private ArrayList<SubcategoryModel> mDataset;
public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public MyViewHolder(View v) {
super(v);
mTextView = (TextView) v.findViewById(R.id.subcategory_text);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(ArrayList<SubcategoryModel> myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
@Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item_subcategory, parent, false);
// set the view's size, margins, paddings and layout parameters
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.mTextView.setText(mDataset.get(position).getSubCategory_name());
}
@Override
public int getItemCount() {
return mDataset.size();
}
}
我现在得到的输出
如您所见,它在每个选项卡中显示相同的结果 "Vitamin & Minerals"..我想要不同的子类别而不是相同的。
问题:
无法在 Bundle
中传递 Serializable
ArrayList
。在此处查看文档页面 Bundle docs
解决方案:
更改 SubCategoryModel
以实现 Parcelable
,然后使用 bundle.putParcelableArrayList(key, list)
和 bundle.getParcelableArrayList(key)
将 ArrayList
传递给 FragmentArgs
并获得他们来自 Fragment
我猜这是您代码的主要逻辑...尝试一下,如果您需要更多帮助或发现它有帮助,请告诉我...
private void parseJsonData() {
try {
listDogs.clear();
JSONArray jsonArray = new JSONArray(loadJSONFromAsset());
JSONObject firstJsonobject = jsonArray.optJSONObject(0);
JSONArray itemListJsonArray = firstJsonobject.optJSONArray("itemList");
JSONObject secondJsonobject = itemListJsonArray.optJSONObject(0);
JSONArray typeMasterArray = secondJsonobject.optJSONArray("typeMaster");
JSONObject thirdJsonobject = typeMasterArray.optJSONObject(0);
JSONArray catMasterArray = thirdJsonobject.optJSONArray("catMaster");
for(int i=0; i<catMasterArray.length(); i++) {
JSONObject jsonObject = catMasterArray.optJSONObject(i);
ModelClass modelClass = new ModelClass();
modelClass.setTypeId(jsonObject.optString("catID"));
modelClass.setTypeName(jsonObject.optString("catName"));
listDogs.add(modelClass);
}
RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(getActivity(), listDogs);
recyclerView.setAdapter(recyclerViewAdapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
注意:为了解析狗类别的数据,我在变量 thirdJsonobject 中传递了 0 个位置。为猫传递 1,为马传递 2,你会找到你想要的输出
截图:
Dogs category
我发现您的代码有很多问题,但让我们让您的 UI 显示子类别,因为这是您主要关心的问题。
将适配器中的 getItem
更改为:
@Override
public Fragment getItem(int position) {
ArrayList<SubcategoryModel> subcategories = filelist.get(position).getItems();
Log.v("adapter", "getitem" + String.valueOf(position)+subcategories.size());
return FirstFragment.create(position,subcategories);
}
导致问题的原因:
让我们关注 activity 中的 ArrayList<SubcategoryModel> subct
:
首先你的代码是这样做的:
for(int i = 0; i < filelist.size(); i++){
ArrayList<SubcategoryModel> subct=filelist.get(i).getItems();
// for(int j=0;j<subct.size();j++) ...
}
所以在此循环结束时 subct
设置了 filelist
中最后一个类别的子类别。
之后,您执行了另一个循环来加载选项卡,但它使用了在循环内声明的不同 subct
变量,并且对您的 subct
字段没有影响activity.
然后您创建了视图寻呼机和适配器。
在你的寻呼机适配器中你有这个:
@Override
public Fragment getItem(int position) {
Log.v("adapter", "getitem" + String.valueOf(position)+subct.size());
return FirstFragment.create(position,subct);
}
由于 subct
被设置为之前循环中的最后一个类别的子类别,因此创建的每个片段都会接收这些子类别,无论片段的位置(类别)是什么。我所做的只是更改代码以返回 filelist
并为正在创建的片段的位置获取正确的类别(和子类别)。
当您编写代码时,您会考虑您希望代码做什么。然而,当你 运行 代码发现你有问题时,你必须忘记你想要代码做什么,然后假装你是计算机并且 运行 你的代码头。您想了解每一行代码的作用。当你这样做时,更容易找到问题。
您好,我有 Tablayout
和 Viewpager
,我正在使用 Fragment
作为 tablayout。现在在每个 Tablayout 片段中我都有 Recyclerview
并显示 items.Please 看到这个我的 json 响应
在 "typeMaster" 中:数组我有类别 "typeName":"Dogs",我在 tablayout 中显示类型名称我有 4 个 tablayout,在 typemaster 中我有子类别名为 "catMaster":我正在尝试在 recyclerview 中显示 catmaster 数据,但问题出在它显示最后数据的每个片段中 "catName":"Vitamins & Minerals",
Activity
public class CategoriesActivity extends AppCompatActivity{
private Header myview;
private ArrayList<SubcategoryModel> subct;
private ArrayList<CategoryModel> filelist;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.categoris_activity);
filelist = (ArrayList<CategoryModel>)getIntent().getSerializableExtra("categorylist");
System.out.println("Category list size"+filelist.size());
myview = (Header) findViewById(R.id.categorisactivity_headerView);
myview.setActivity(this);
TabLayout tabLayout = (TabLayout) findViewById(R.id.cat_tab_layout);
for(int i = 0; i < filelist.size(); i++){
subct=filelist.get(i).getItems();
for(int j=0;j<subct.size();j++)
{
}
System.out.println("SubCategory list size"+subct.size());
}
for(int i = 0; i < filelist.size(); i++){
tabLayout.addTab(tabLayout.newTab().setText(filelist.get(i).getCategory_typename()));
ArrayList<SubcategoryModel> subct=filelist.get(i).getItems();
for(int j=0;j<subct.size();j++)
{
}
}
Bundle bundleObject = new Bundle();
bundleObject.putSerializable("key", filelist);
FirstFragment ff=new FirstFragment();
ff.setArguments(bundleObject);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
final ViewPager viewPager = (ViewPager) findViewById(R.id.categories_pager);
CategoriesAdapter mPagerAdapter = new CategoriesAdapter(getSupportFragmentManager(),tabLayout.getTabCount());
viewPager.setAdapter(mPagerAdapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
public class CategoriesAdapter extends FragmentStatePagerAdapter {
ArrayList<CategoryModel> catlist;
int numoftabs;
public CategoriesAdapter(FragmentManager fm, int numoftabs) {
super(fm);
this.numoftabs = numoftabs;
}
@Override
public Fragment getItem(int position) {
Log.v("adapter", "getitem" + String.valueOf(position)+subct.size());
return FirstFragment.create(position,subct);
}
@Override
public int getCount() {
return numoftabs;
}
}
}
片段
public class FirstFragment extends Fragment {
// Store instance variables
public static final String ARG_PAGE = "page";
private int mPageNumber;
private Context mContext;
private int Cimage;
private ArrayList<SubcategoryModel> subcatlist;
private RecyclerView rcylervw;
private ArrayList<CategoryModel> filelist;
ArrayList<SubcategoryModel> subct;
public static FirstFragment create(int pageNumber,ArrayList<SubcategoryModel> subct){
FirstFragment fragment = new FirstFragment();
Bundle args = new Bundle();
args.putInt(ARG_PAGE, pageNumber);
args.putSerializable("key", subct);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPageNumber = getArguments().getInt(ARG_PAGE);
subct= (ArrayList<SubcategoryModel>) getArguments().getSerializable("key");
System.out.println("Frag Category list size"+subct.size());
/* for(int i = 0; i < filelist.size(); i++){
subct=filelist.get(i).getItems();
for(int j=0;j<subct.size();j++)
{
}
System.out.println("Frag SubCategory list size"+subct.size());
}*/
// image uri get uri of image that saved in directory of app
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater
.inflate(R.layout.test, container, false);
rcylervw=(RecyclerView)rootView.findViewById(R.id.subcategory_recycler_view);
rcylervw.setHasFixedSize(true);
MyAdapter adapter = new MyAdapter(subct);
rcylervw.setAdapter(adapter);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rcylervw.setLayoutManager(llm);
return rootView;
}
// this method is not very important
}
我的适配器
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private ArrayList<SubcategoryModel> mDataset;
public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public MyViewHolder(View v) {
super(v);
mTextView = (TextView) v.findViewById(R.id.subcategory_text);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(ArrayList<SubcategoryModel> myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
@Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item_subcategory, parent, false);
// set the view's size, margins, paddings and layout parameters
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.mTextView.setText(mDataset.get(position).getSubCategory_name());
}
@Override
public int getItemCount() {
return mDataset.size();
}
}
我现在得到的输出
如您所见,它在每个选项卡中显示相同的结果 "Vitamin & Minerals"..我想要不同的子类别而不是相同的。
问题:
无法在 Bundle
中传递 Serializable
ArrayList
。在此处查看文档页面 Bundle docs
解决方案:
更改 SubCategoryModel
以实现 Parcelable
,然后使用 bundle.putParcelableArrayList(key, list)
和 bundle.getParcelableArrayList(key)
将 ArrayList
传递给 FragmentArgs
并获得他们来自 Fragment
我猜这是您代码的主要逻辑...尝试一下,如果您需要更多帮助或发现它有帮助,请告诉我...
private void parseJsonData() {
try {
listDogs.clear();
JSONArray jsonArray = new JSONArray(loadJSONFromAsset());
JSONObject firstJsonobject = jsonArray.optJSONObject(0);
JSONArray itemListJsonArray = firstJsonobject.optJSONArray("itemList");
JSONObject secondJsonobject = itemListJsonArray.optJSONObject(0);
JSONArray typeMasterArray = secondJsonobject.optJSONArray("typeMaster");
JSONObject thirdJsonobject = typeMasterArray.optJSONObject(0);
JSONArray catMasterArray = thirdJsonobject.optJSONArray("catMaster");
for(int i=0; i<catMasterArray.length(); i++) {
JSONObject jsonObject = catMasterArray.optJSONObject(i);
ModelClass modelClass = new ModelClass();
modelClass.setTypeId(jsonObject.optString("catID"));
modelClass.setTypeName(jsonObject.optString("catName"));
listDogs.add(modelClass);
}
RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(getActivity(), listDogs);
recyclerView.setAdapter(recyclerViewAdapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
注意:为了解析狗类别的数据,我在变量 thirdJsonobject 中传递了 0 个位置。为猫传递 1,为马传递 2,你会找到你想要的输出
截图: Dogs category
我发现您的代码有很多问题,但让我们让您的 UI 显示子类别,因为这是您主要关心的问题。
将适配器中的 getItem
更改为:
@Override
public Fragment getItem(int position) {
ArrayList<SubcategoryModel> subcategories = filelist.get(position).getItems();
Log.v("adapter", "getitem" + String.valueOf(position)+subcategories.size());
return FirstFragment.create(position,subcategories);
}
导致问题的原因:
让我们关注 activity 中的 ArrayList<SubcategoryModel> subct
:
首先你的代码是这样做的:
for(int i = 0; i < filelist.size(); i++){
ArrayList<SubcategoryModel> subct=filelist.get(i).getItems();
// for(int j=0;j<subct.size();j++) ...
}
所以在此循环结束时 subct
设置了 filelist
中最后一个类别的子类别。
之后,您执行了另一个循环来加载选项卡,但它使用了在循环内声明的不同 subct
变量,并且对您的 subct
字段没有影响activity.
然后您创建了视图寻呼机和适配器。
在你的寻呼机适配器中你有这个:
@Override
public Fragment getItem(int position) {
Log.v("adapter", "getitem" + String.valueOf(position)+subct.size());
return FirstFragment.create(position,subct);
}
由于 subct
被设置为之前循环中的最后一个类别的子类别,因此创建的每个片段都会接收这些子类别,无论片段的位置(类别)是什么。我所做的只是更改代码以返回 filelist
并为正在创建的片段的位置获取正确的类别(和子类别)。
当您编写代码时,您会考虑您希望代码做什么。然而,当你 运行 代码发现你有问题时,你必须忘记你想要代码做什么,然后假装你是计算机并且 运行 你的代码头。您想了解每一行代码的作用。当你这样做时,更容易找到问题。