为什么我的 activity 在尝试搜索回收站视图时会崩溃?

Why does my activity crash when trying to search recycler view?

我遇到了一个问题,我想在回收站视图加载时显示一个循环加载进度条,并且只在完全加载时显示回收站视图,因为当我在回收站视图中搜索项目时崩溃给我错误:

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 1(offset:1).state:8077 androidx.recyclerview.widget.RecyclerView{e6252d0 VFED....

避免崩溃的唯一方法是等待大约 4 秒并滚动一点直到它完全加载。并且 activity 只有在它可以明显显示回收视图时才会打开,这也会给它带来延迟。

那么我该如何解决这个错误,也许是在它完全加载后才显示回收视图和搜索栏?

    private void getAllStocks() {

        try {

            String[] nasdaqLine;
            String[] nyseLine;
           while ((nasdaqLine = nasdaqReader.readNext()) != null){

                nasdaqSymbol = nasdaqLine[0];
                nasdaqFullName = nasdaqLine[1];
                sector = nasdaqLine[5];
                industry = nasdaqLine[6];


                stocksList.add(new StocksList(nasdaqSymbol, nasdaqFullName, sector, industry));


            }

            while ((nyseLine = nyseReader.readNext()) != null){

                nyseSymbol = nyseLine[0];
                nyseFullName = nyseLine[1];


                stocksList.add(new StocksList(nyseSymbol, "", nyseFullName, null));

            }


        } catch (IOException e) {
            e.printStackTrace();
        }

}

这就是我填充回收站视图的方式。

    getAllStocks();


        layoutManager = new LinearLayoutManager(this, RecyclerView.VERTICAL, false);
        adapter = new StocksListAdapter(stocksList);

        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setAdapter(adapter);

        if (stocksList.size() == 8893) {
            adapter.notifyDataSetChanged();
            circularProgressBar.setVisibility(View.GONE);
            recyclerView.setVisibility(View.VISIBLE);

        }

这就是我尝试仅在它完全加载后才显示它的方式,但 activity 仅在它可以明显显示回收站视图后才打开。

public Filter getFilter() {
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence charSequence) {

                String Key = charSequence.toString();
                if (Key.isEmpty()){

                    stocksListFilterd = stocksList;

                } else {

                    ArrayList<StocksList> listFiltered = new ArrayList<>();

                    for (StocksList stock : stocksList){

                        if (stock.getFullName().toLowerCase().contains(Key.toLowerCase()) || stock.getSymbol().toLowerCase().contains(Key.toLowerCase())
                                || stock.getSector().toLowerCase().contains(Key.toLowerCase())){
                            listFiltered.add(stock);
                        }
                    }

                    stocksListFilterd = listFiltered;

                }

                FilterResults filterResults = new FilterResults();
                filterResults.values = stocksListFilterd;
                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
                stocksListFilterd = (ArrayList<StocksList>) filterResults.values;
                notifyDataSetChanged();
            }
        };
    }

这是我适配器中的过滤器 class

您尝试在 RecyclerView 中显示的数据是否有可能在其他地方的不同线程中被修改?这可能会解释您看到的 Inconsistency detected 错误消息。

如果您通过搜索过滤 RecyclerView 中的数据,请确保之后调用 notifyDataSetChanged() 以刷新 RecyclerView 中的数据。

你没有显示你在哪里调用 getFilter(),但它似乎没有在 publishResults() 方法中使用 notifyDataSetChanged()。根据您的代码结构,尝试调用 notifyDataSetChanged(),其中 return 来自 return filterResults.

的数据

想出了如何修复另一个视频的错误,它几乎只是一个更简单的过滤器重写

在我填充回收站视图的地方,我所做的就是添加这个

  while ((nyseLine = nyseReader.readNext()) != null){

                nyseSymbol = nyseLine[0];
                nyseFullName = nyseLine[1];


                stocksList.add(new StocksList(nyseSymbol, "", nyseFullName, null));

            }

            //I added this to set the adapter and show the list immediately after 
            //loading   
            adapter = new StocksListAdapter(stocksList);
            recyclerView.setAdapter(adapter);
            adapter.notifyDataSetChanged();

然后我在 The SAME activity 中创建了这个方法,而不是在适配器 class

 private void Filter(String searched) {

        for (StocksList stock : stocksList ){
            if (stock.getSymbol().toLowerCase().equals(searched)){
                //created new array list for the filter       
                filteredList.add(stock);
            }
        }
        recyclerView.setAdapter(new StocksListAdapter(filteredList));
        adapter.notifyDataSetChanged();

    }

这是 OnCreate class editText 侦听器

 recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setHasFixedSize(true);

        searchStocks.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            //Moved the the stuff to afterTextChanged not onTextChanged        
            @Override
            public void afterTextChanged(Editable editable) {

                filteredList.clear();

                if (editable.toString().isEmpty()){
                    recyclerView.setAdapter(new StocksListAdapter(stocksList));
                    adapter.notifyDataSetChanged();
                } else {
                    Filter(editable.toString());
                }
            }
        });

我很确定错误是我在一个方法中设置了所有回收器视图值,如 recyclerview.setAdapter(new StocksListAdapter(stocksList),我在 oncreate 方法中调用了 once 当它需要用新的过滤列表更新适配器时 adapter.notifyDataSetChanged() 无法访问并且没有做任何事情。

因此在适配器 class 内部,它来回处理不一致的列表,因此崩溃。不过这只是我的猜测,@shagberg 的评论真的很有帮助。

P.S 将来遇到此问题的任何其他人:检查您的 notifyDataSetChanged() 调用,确保它们不在 Filter 调用或其他数据更改方法之后,因为如果它在错误的地方它崩溃了。