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();