Android ViewPager2 RecyclerView notifyDataSetChanged() 不工作
Android ViewPager2 RecyclerView notifyDataSetChanged() not working
我正在使用 ViewPager2 和 RecyclerView 开发搜索 activity。
我想要的是使用在 EditText 中输入的文本作为请求参数,并将响应数据反映在 RecyclerView 中。
我检查数据是正常响应的,但是没有反映到视图中。
看了那么多问题和帖子,还是没能解决视图不刷新的问题
经查,数据添加到RecyclerView的列表中,RecyclerView Adapter的方法根本没有执行。
SearchActivity
public class SearchActivity extends AppCompatActivity {
private ActivitySearchBinding binding;
private static final int[] TAB_TITLES = new int[]{R.string.tab_text_1, R.string.tab_text_2};
private final String key;
private BusStopInterface busStopInterface;
private PlaceholderFragment fragment;
private SectionsPagerAdapter sectionsPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySearchBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
sectionsPagerAdapter = new SectionsPagerAdapter(SearchActivity.this);
ViewPager2 pager = binding.viewPager;
pager.setAdapter(sectionsPagerAdapter);
TabLayout tabs = binding.tabs;
EditText searchBox = binding.searchBox;
fragment = new PlaceholderFragment();
new TabLayoutMediator(tabs, pager, (tab, position) -> tab.setText(TAB_TITLES[position])).attach();
RetrofitClient retrofitClient = RetrofitClient.getInstance();
busStopInterface = RetrofitClient.getRetrofitInterface();
searchBox.addTextChangedListener(textWatcher);
pager.registerOnPageChangeCallback(pageChangeCallback);
}
ViewPager2.OnPageChangeCallback pageChangeCallback = new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
if (position == 0) {
Log.d("position", "Bus stop");;
} else if (position == 1) {
Log.d("position", "Bus");;
}
}
};
TextWatcher textWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
busStopInterface.getBusStop(key, 25, "json", 25, s.toString()).enqueue(new Callback<Example>() {
@Override
public void onResponse(Call<Example> call, Response<Example> response) {
if (response.isSuccessful()) {
Example example = response.body();
Items items = example.getResult().getBody().getItems(); //I checked the data response.
fragment.resetRecyclerView(items.getItem());
sectionsPagerAdapter.notifyDataSetChanged();
Log.d("retrofit", "Data fetch success");
} else {
Log.d("retrofit", "Data fetch fail");
}
}
@Override
public void onFailure(Call<Example> call, Throwable t) {
Log.d("retrofit", t.getMessage());
}
});
}
};
}
PlaceholderFragment
public class PlaceholderFragment extends Fragment {
private static final String ARG_SECTION_NUMBER = "section_number";
private PageViewModel pageViewModel;
private FragmentSearchBinding binding;
public List<BusStopItem> items = new ArrayList<>();
public SearchRecyclerViewAdapter adapter = new SearchRecyclerViewAdapter(items);
public static PlaceholderFragment newInstance(int index) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle bundle = new Bundle();
bundle.putInt(ARG_SECTION_NUMBER, index);
fragment.setArguments(bundle);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
pageViewModel = new ViewModelProvider(this).get(PageViewModel.class);
int index = 1;
if (getArguments() != null) {
index = getArguments().getInt(ARG_SECTION_NUMBER);
}
pageViewModel.setIndex(index);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
binding = FragmentSearchBinding.inflate(inflater, container, false);
View root = binding.getRoot();
pageViewModel.getIndex().observe(getViewLifecycleOwner(), new Observer<Integer>() {
@Override
public void onChanged(Integer index) {
if (index == 1) {
adapter.setItemViewType(SearchRecyclerViewAdapter.VIEWTYPE_BUS_STOP);
} else if (index == 2) {
adapter.setItemViewType(SearchRecyclerViewAdapter.VIEWTYPE_BUS);
}
}
});
return root;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
RecyclerView recyclerView = binding.searchRecyclerView;
recyclerView.setAdapter(adapter);
recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), 1));
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
public void resetRecyclerView(List<BusStopItem> newItems) {
items.clear();
items.addAll(newItems);
adapter.notifyDataSetChanged();
}
}
SearchRecyclerViewAdapter
public class SearchRecyclerViewAdapter extends RecyclerView.Adapter<SearchRecyclerViewAdapter.ViewHolder> {
public static final int VIEWTYPE_BUS_STOP = 0;
public static final int VIEWTYPE_BUS = 1;
int mItemViewType;
List<BusStopItem> busStopItems;
public class ViewHolder extends RecyclerView.ViewHolder {
TextView busStopName, busStopId, busStopLocation, busName, busArea, busRoute;
public ViewHolder(@NonNull View itemView) {
super(itemView);
busStopName = itemView.findViewById(R.id.busStopName);
busStopId = itemView.findViewById(R.id.busStopId);
busStopLocation = itemView.findViewById(R.id.busStopLocation);
busName = itemView.findViewById(R.id.busName);
busArea = itemView.findViewById(R.id.busArea);
busRoute = itemView.findViewById(R.id.busRoute);
}
public void setBusStopItem(BusStopItem item) {
busStopName.setText(item.getNodenm());
if(item.getNodeno() != null) {
busStopId.setText(item.getNodeno().toString());
}
}
}
public SearchRecyclerViewAdapter(List<BusStopItem> busStopItems) {
this.busStopItems = busStopItems;
}
public void setItemViewType(int viewType) {
mItemViewType = viewType;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = null;
if (viewType == VIEWTYPE_BUS_STOP) {
view = inflater.inflate(R.layout.search_bus_stop_item, parent, false);
} else if (viewType == VIEWTYPE_BUS) {
view = inflater.inflate(R.layout.search_bus_item, parent, false);
}
SearchRecyclerViewAdapter.ViewHolder vh = new SearchRecyclerViewAdapter.ViewHolder(view);
return vh;
}
@Override
public int getItemViewType(int position) {
return mItemViewType;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
if (mItemViewType == VIEWTYPE_BUS_STOP) {
holder.setBusStopItem(busStopItems.get(position));
} else if (mItemViewType == VIEWTYPE_BUS) {
}
}
@Override
public int getItemCount() {
return busStopItems.size();
}
}
SectionsPagerAdapter
public class SectionsPagerAdapter extends FragmentStateAdapter {
public SectionsPagerAdapter(FragmentActivity fa) {
super(fa);
}
@NonNull
@Override
public Fragment createFragment(int position) {
return PlaceholderFragment.newInstance(position + 1);
}
@Override
public int getItemCount() {
return 2;
}
}
我试过的
public void resetRecyclerView(List<BusStopItem> newItems) {
items.clear();
items.addAll(newItems);
adapter.notifyDataSetChanged();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(this).attach(this).commit();
}
java.lang.NullPointerException: 尝试在空对象引用
上调用虚拟方法'androidx.fragment.app.FragmentTransaction androidx.fragment.app.FragmentManager.beginTransaction()'
您创建了 PlaceholderFragment
但没有将其添加到 FragmmentManger
。
fragment = new PlaceholderFragment();
当 `busStopInterface.getBusStop()` 得到 return 时,您将数据设置为
private PlaceholderFragment fragment
并且片段未附加到任何 Activity,因此 UI 不会刷新。
您应该从 SectionsPagerAdapter
获取 PlaceholderFragment
实例或为 SectionsPagerAdapter
创建 PlaceholderFragment
实例,并且您可以将数据设置为真实 PlaceholderFragment
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySearchBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
fragments = new ArrayList<>();
fragments.add(PlaceholderFragment.newInstance(1));
fragments.add(PlaceholderFragment.newInstance(2));
sectionsPagerAdapter = new SectionsPagerAdapter(SearchActivity.this, fragments);
ViewPager2 pager = binding.viewPager;
pager.setAdapter(sectionsPagerAdapter);
TabLayout tabs = binding.tabs;
EditText searchBox = binding.searchBox;
new TabLayoutMediator(tabs, pager, (tab, position) -> tab.setText(TAB_TITLES[position])).attach();
RetrofitClient retrofitClient = RetrofitClient.getInstance();
busStopInterface = RetrofitClient.getRetrofitInterface();
searchBox.addTextChangedListener(textWatcher);
pager.registerOnPageChangeCallback(pageChangeCallback);
}
public class SectionsPagerAdapter extends FragmentStateAdapter {
private final List<PlaceholderFragment> fragments;
public SectionsPagerAdapter(FragmentActivity fa, List<PlaceholderFragment> fragments) {
super(fa);
this.fragments = fragments;
}
@NonNull
@Override
public Fragment createFragment(int position) {
return fragments.get(position);
}
@Override
public int getItemCount() {
return 2;
}
}
busStopInterface.getBusStop(key, 25, "json", 25, s.toString()).enqueue(new Callback<Example>() {
@Override
public void onResponse(Call<Example> call, Response<Example> response) {
if (response.isSuccessful()) {
Example example = response.body();
Items items = example.getResult().getBody().getItems(); //I checked the data response.
fragments.get(1).resetRecyclerView(items.getItem());
Log.d("retrofit", "Data fetch success");
} else {
Log.d("retrofit", "Data fetch fail");
}
}
@Override
public void onFailure(Call<Example> call, Throwable t) {
Log.d("retrofit", t.getMessage());
}
});
PS。移除
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(this).attach(this).commit();
我正在使用 ViewPager2 和 RecyclerView 开发搜索 activity。
我想要的是使用在 EditText 中输入的文本作为请求参数,并将响应数据反映在 RecyclerView 中。
我检查数据是正常响应的,但是没有反映到视图中。
看了那么多问题和帖子,还是没能解决视图不刷新的问题
经查,数据添加到RecyclerView的列表中,RecyclerView Adapter的方法根本没有执行。
SearchActivity
public class SearchActivity extends AppCompatActivity {
private ActivitySearchBinding binding;
private static final int[] TAB_TITLES = new int[]{R.string.tab_text_1, R.string.tab_text_2};
private final String key;
private BusStopInterface busStopInterface;
private PlaceholderFragment fragment;
private SectionsPagerAdapter sectionsPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySearchBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
sectionsPagerAdapter = new SectionsPagerAdapter(SearchActivity.this);
ViewPager2 pager = binding.viewPager;
pager.setAdapter(sectionsPagerAdapter);
TabLayout tabs = binding.tabs;
EditText searchBox = binding.searchBox;
fragment = new PlaceholderFragment();
new TabLayoutMediator(tabs, pager, (tab, position) -> tab.setText(TAB_TITLES[position])).attach();
RetrofitClient retrofitClient = RetrofitClient.getInstance();
busStopInterface = RetrofitClient.getRetrofitInterface();
searchBox.addTextChangedListener(textWatcher);
pager.registerOnPageChangeCallback(pageChangeCallback);
}
ViewPager2.OnPageChangeCallback pageChangeCallback = new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
if (position == 0) {
Log.d("position", "Bus stop");;
} else if (position == 1) {
Log.d("position", "Bus");;
}
}
};
TextWatcher textWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
busStopInterface.getBusStop(key, 25, "json", 25, s.toString()).enqueue(new Callback<Example>() {
@Override
public void onResponse(Call<Example> call, Response<Example> response) {
if (response.isSuccessful()) {
Example example = response.body();
Items items = example.getResult().getBody().getItems(); //I checked the data response.
fragment.resetRecyclerView(items.getItem());
sectionsPagerAdapter.notifyDataSetChanged();
Log.d("retrofit", "Data fetch success");
} else {
Log.d("retrofit", "Data fetch fail");
}
}
@Override
public void onFailure(Call<Example> call, Throwable t) {
Log.d("retrofit", t.getMessage());
}
});
}
};
}
PlaceholderFragment
public class PlaceholderFragment extends Fragment {
private static final String ARG_SECTION_NUMBER = "section_number";
private PageViewModel pageViewModel;
private FragmentSearchBinding binding;
public List<BusStopItem> items = new ArrayList<>();
public SearchRecyclerViewAdapter adapter = new SearchRecyclerViewAdapter(items);
public static PlaceholderFragment newInstance(int index) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle bundle = new Bundle();
bundle.putInt(ARG_SECTION_NUMBER, index);
fragment.setArguments(bundle);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
pageViewModel = new ViewModelProvider(this).get(PageViewModel.class);
int index = 1;
if (getArguments() != null) {
index = getArguments().getInt(ARG_SECTION_NUMBER);
}
pageViewModel.setIndex(index);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
binding = FragmentSearchBinding.inflate(inflater, container, false);
View root = binding.getRoot();
pageViewModel.getIndex().observe(getViewLifecycleOwner(), new Observer<Integer>() {
@Override
public void onChanged(Integer index) {
if (index == 1) {
adapter.setItemViewType(SearchRecyclerViewAdapter.VIEWTYPE_BUS_STOP);
} else if (index == 2) {
adapter.setItemViewType(SearchRecyclerViewAdapter.VIEWTYPE_BUS);
}
}
});
return root;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
RecyclerView recyclerView = binding.searchRecyclerView;
recyclerView.setAdapter(adapter);
recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), 1));
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
public void resetRecyclerView(List<BusStopItem> newItems) {
items.clear();
items.addAll(newItems);
adapter.notifyDataSetChanged();
}
}
SearchRecyclerViewAdapter
public class SearchRecyclerViewAdapter extends RecyclerView.Adapter<SearchRecyclerViewAdapter.ViewHolder> {
public static final int VIEWTYPE_BUS_STOP = 0;
public static final int VIEWTYPE_BUS = 1;
int mItemViewType;
List<BusStopItem> busStopItems;
public class ViewHolder extends RecyclerView.ViewHolder {
TextView busStopName, busStopId, busStopLocation, busName, busArea, busRoute;
public ViewHolder(@NonNull View itemView) {
super(itemView);
busStopName = itemView.findViewById(R.id.busStopName);
busStopId = itemView.findViewById(R.id.busStopId);
busStopLocation = itemView.findViewById(R.id.busStopLocation);
busName = itemView.findViewById(R.id.busName);
busArea = itemView.findViewById(R.id.busArea);
busRoute = itemView.findViewById(R.id.busRoute);
}
public void setBusStopItem(BusStopItem item) {
busStopName.setText(item.getNodenm());
if(item.getNodeno() != null) {
busStopId.setText(item.getNodeno().toString());
}
}
}
public SearchRecyclerViewAdapter(List<BusStopItem> busStopItems) {
this.busStopItems = busStopItems;
}
public void setItemViewType(int viewType) {
mItemViewType = viewType;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = null;
if (viewType == VIEWTYPE_BUS_STOP) {
view = inflater.inflate(R.layout.search_bus_stop_item, parent, false);
} else if (viewType == VIEWTYPE_BUS) {
view = inflater.inflate(R.layout.search_bus_item, parent, false);
}
SearchRecyclerViewAdapter.ViewHolder vh = new SearchRecyclerViewAdapter.ViewHolder(view);
return vh;
}
@Override
public int getItemViewType(int position) {
return mItemViewType;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
if (mItemViewType == VIEWTYPE_BUS_STOP) {
holder.setBusStopItem(busStopItems.get(position));
} else if (mItemViewType == VIEWTYPE_BUS) {
}
}
@Override
public int getItemCount() {
return busStopItems.size();
}
}
SectionsPagerAdapter
public class SectionsPagerAdapter extends FragmentStateAdapter {
public SectionsPagerAdapter(FragmentActivity fa) {
super(fa);
}
@NonNull
@Override
public Fragment createFragment(int position) {
return PlaceholderFragment.newInstance(position + 1);
}
@Override
public int getItemCount() {
return 2;
}
}
我试过的
public void resetRecyclerView(List<BusStopItem> newItems) {
items.clear();
items.addAll(newItems);
adapter.notifyDataSetChanged();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(this).attach(this).commit();
}
java.lang.NullPointerException: 尝试在空对象引用
上调用虚拟方法'androidx.fragment.app.FragmentTransaction androidx.fragment.app.FragmentManager.beginTransaction()'您创建了 PlaceholderFragment
但没有将其添加到 FragmmentManger
。
fragment = new PlaceholderFragment();
当 `busStopInterface.getBusStop()` 得到 return 时,您将数据设置为
private PlaceholderFragment fragment
并且片段未附加到任何 Activity,因此 UI 不会刷新。
您应该从 SectionsPagerAdapter
获取 PlaceholderFragment
实例或为 SectionsPagerAdapter
创建 PlaceholderFragment
实例,并且您可以将数据设置为真实 PlaceholderFragment
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySearchBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
fragments = new ArrayList<>();
fragments.add(PlaceholderFragment.newInstance(1));
fragments.add(PlaceholderFragment.newInstance(2));
sectionsPagerAdapter = new SectionsPagerAdapter(SearchActivity.this, fragments);
ViewPager2 pager = binding.viewPager;
pager.setAdapter(sectionsPagerAdapter);
TabLayout tabs = binding.tabs;
EditText searchBox = binding.searchBox;
new TabLayoutMediator(tabs, pager, (tab, position) -> tab.setText(TAB_TITLES[position])).attach();
RetrofitClient retrofitClient = RetrofitClient.getInstance();
busStopInterface = RetrofitClient.getRetrofitInterface();
searchBox.addTextChangedListener(textWatcher);
pager.registerOnPageChangeCallback(pageChangeCallback);
}
public class SectionsPagerAdapter extends FragmentStateAdapter {
private final List<PlaceholderFragment> fragments;
public SectionsPagerAdapter(FragmentActivity fa, List<PlaceholderFragment> fragments) {
super(fa);
this.fragments = fragments;
}
@NonNull
@Override
public Fragment createFragment(int position) {
return fragments.get(position);
}
@Override
public int getItemCount() {
return 2;
}
}
busStopInterface.getBusStop(key, 25, "json", 25, s.toString()).enqueue(new Callback<Example>() {
@Override
public void onResponse(Call<Example> call, Response<Example> response) {
if (response.isSuccessful()) {
Example example = response.body();
Items items = example.getResult().getBody().getItems(); //I checked the data response.
fragments.get(1).resetRecyclerView(items.getItem());
Log.d("retrofit", "Data fetch success");
} else {
Log.d("retrofit", "Data fetch fail");
}
}
@Override
public void onFailure(Call<Example> call, Throwable t) {
Log.d("retrofit", t.getMessage());
}
});
PS。移除
FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.detach(this).attach(this).commit();