【问题标题】:IndexOutOfBoundsException: Inconsistency detectedIndexOutOfBoundsException:检测到不一致
【发布时间】:2017-04-17 23:56:34
【问题描述】:

我正在使用 recyclerView 并将数据加载为 arrayList。如果 arrayList 的项少于 7 个,则不会崩溃。

否则,我有这个致命错误:

java.lang.IndexOutOfBoundsException:检测到不一致。无效的视图支架适配器 positionViewHolder{3b1755be position=7 id=-1, oldPos=-1, pLpos:-1 no parent}

谁能帮忙?

DiagnosticAdapter.java

public class DiagnosticAdapter extends RecyclerView.Adapter<DiagnosticAdapter.ViewHolder> implements Filterable {
    public static ArrayList<Diagnostic> diagnostics;
    private ArrayList<Diagnostic> mFilteredDiagnosticArray;


    public DiagnosticAdapter(ArrayList<Diagnostic> diagnostics) {
        this.diagnostics = diagnostics;

    }

    @Override
    public DiagnosticAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_row, viewGroup, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(DiagnosticAdapter.ViewHolder viewHolder, int i) {

        viewHolder.parameter.setText(diagnostics.get(i).getParameter());
        viewHolder.value.setText(diagnostics.get(i).getValue());
    }

    @Override
    public Filter getFilter() {

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

                String charString = charSequence.toString();

                if (charString.isEmpty()) {

                    mFilteredDiagnosticArray = diagnostics;
                } else {
                    ArrayList<Diagnostic> filteredList = new ArrayList<>();

                    for (Diagnostic diagnostic : diagnostics) {

                        if (diagnostic.getParameter().toLowerCase().contains(charString) || diagnostic.getValue().toLowerCase().contains(charString)) {

                            filteredList.add(diagnostic);
                        }
                    }

                    mFilteredDiagnosticArray = filteredList;

                }

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

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

    @Override
    public int getItemCount() {
        return diagnostics.size();
    }

}

ViewHolder.java

public class ViewHolder extends RecyclerView.ViewHolder{
    private TextView parameter, value;
    public ViewHolder(View view) {
        super(view);
        parameter = (TextView)view.findViewById(R.id.parameter);
        value = (TextView)view.findViewById(R.id.value);
    }
}

Fragment1.java

public class Fragment1 extends Fragment   {
    private PtrClassicFrameLayout mPtrFrame;
    private RecyclerView recyclerView;
    private ArrayList<Diagnostic> data;
    public static DiagnosticAdapter adapter;
    private  OkHttpClient client;
    private  Handler handler;
    public static String constVar;
    private String method;
    public Fragment1() {

    }
    private Boolean mIsRefreshing = false;
    private String ipAddress;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        return inflater.inflate(R.layout.fragment_1, container, false);
    }

    @Override
    public void onViewCreated(final View view, @Nullable final Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        recyclerView = (RecyclerView) view.findViewById(R.id.recycler_viewDiag);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new WrapContentLinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
        Log.i("mIsRefreshing",mIsRefreshing.toString());
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
            method = getArguments().getString("method");
            Log.i("METHOD",method);

            loadJSON();

        }else{
        }
    }

    private void loadJSON(){
       // Log.i("Fragment1",ipAddress);
        Retrofit retrofit = new Retrofit.Builder()
                //.baseUrl("http://"+ipAddress+":8000")
               .baseUrl("http://10.206.208.92"+":8000")
                .addConverterFactory(GsonConverterFactory.create())
                .build();


        RequestInterface request = retrofit.create(RequestInterface.class);
        Call<JSONResponse> call ;
        switch (method){
            case "identification":
                call = request.getIdentification();
                break;
            case "memory":
                call = request.getMemory();
                break;
            case "sysInfo":
                call = request.getSysInfo();
                break;
            case "conditionalAccess":
                call = request.getConditionalAccess();
                break;
            case "network":
                call = request.getNetwork();
                break;
            case "software":
                call = request.getSoftware();
                break;
            case "loader":
                call = request.getLoader();
                break;
            default:
                call = request.getJSON();
                break;
        }

        call.enqueue(new Callback<JSONResponse>() {
            @Override
            public void onResponse(Call<JSONResponse> call, Response<JSONResponse> response) {
                JSONResponse jsonResponse = response.body();
                switch (method){
                    case "identification":
                        data = new ArrayList<>(Arrays.asList(jsonResponse.getIdentification()));
                        break;
                    case "memory":
                        data = new ArrayList<>(Arrays.asList(jsonResponse.getMemory()));
                        break;
                    case "sysInfo":
                        data = new ArrayList<>(Arrays.asList(jsonResponse.getSysInfo()));
                        break;
                    case "conditionalAccess":
                        data = new ArrayList<>(Arrays.asList(jsonResponse.getConditionalAccess()));
                        break;
                    case "network":
                        data = new ArrayList<>(Arrays.asList(jsonResponse.getNetwork()));
                        break;
                    case "software":
                        data = new ArrayList<>(Arrays.asList(jsonResponse.getSoftware()));
                        break;
                    case "loader":
                        data = new ArrayList<>(Arrays.asList(jsonResponse.getLoader()));
                        break;
                    default:
                        data = new ArrayList<>(Arrays.asList(jsonResponse.getDiagnostics()));
                        break;

                }
                //data = new ArrayList<>(Arrays.asList(jsonResponse.getDiagnostics()));
                //Toast.makeText(getContext(), data.size(), Toast.LENGTH_LONG).show();
                adapter = new DiagnosticAdapter(data);
                recyclerView.setAdapter(adapter);
                adapter.notifyDataSetChanged();
                mIsRefreshing = true;
                Log.i("mIsRefreshing",mIsRefreshing.toString());


                //  mPtrFrame.refreshComplete();

            }
            @Override
            public void onFailure(Call<JSONResponse> call, Throwable t) {
              //  mPtrFrame.refreshComplete();
                try {
                    adapter.diagnostics.clear();
                    adapter.notifyDataSetChanged();
                } catch (Exception e) {
                    Log.e("ERROR", "showProgressDialog", e);
            }
                Snackbar.make(getView(), "Unable to fetch json: " + t.getMessage(), Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }
}

DemoActivity.java

public class DemoActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_demo);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        final ViewPager viewPager = (ViewPager) findViewById(R.id.viewpagerDemo);
        // final ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
        SmartTabLayout viewPagerTab = (SmartTabLayout)
        findViewById(R.id.viewpagertab);


        TabsAdapter adapter = new TabsAdapter(getSupportFragmentManager());
        adapter.addFrag(new Fragment1(), "memory");
        adapter.addFrag(new Fragment1(), "identification");
        adapter.addFrag(new Fragment1(), "loader");
        viewPager.setAdapter(adapter);
        viewPagerTab.setViewPager(viewPager);
    }
}

TabsAdapter.java

public class TabsAdapter extends FragmentPagerAdapter {
    private final List<android.support.v4.app.Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();
    public TabsAdapter(FragmentManager fm) {
      super(fm);
    }
    public void addFrag(android.support.v4.app.Fragment fragment, String title){
      Bundle bundle = new Bundle();
      bundle.putString("method", title);
      fragment.setArguments(bundle);

      mFragmentList.add(fragment);
      mFragmentTitleList.add(title);
    }
    @Override
    public android.support.v4.app.Fragment getItem(int position) {
      return mFragmentList.get(position);
    }
    @Override
    public int getCount() {
      return mFragmentList.size();
    }
    @Override
    public CharSequence getPageTitle(int position) {
      return mFragmentTitleList.get(position);
    }
}

【问题讨论】:

  • 请发布适配器类实现。另外请检查您初始化数据数组的方式。在初始化 arralylist 时检查是否缺少任何索引。
  • 我猜测一下,当您没有崩溃并且它们完全填满您的屏幕时,活动中还有 7 项可见?
  • @Totumus Maximus 是的
  • 您是否在其他任何地方修改了适配器的内容?届时别忘了致电adapter.notifyDataSetChanged()
  • @beeb 不,仅在片段中

标签: android android-recyclerview


【解决方案1】:

您可以尝试使用适配器中的数据副本吗?

private ArrayList<Diagnostic> diagnostics = new ArrayList<>();
public DiagnosticAdapter(ArrayList<Diagnostic> diagnostics) {
  this.diagnostics.addAll(diagnostics);
}

像这样清除数据:

public void clearData() {
  this.diagnostics.clear();
  notifyDataSetChanged();
}

像这样设置新数据:

public void setData(List<Diagnostics> data) {
  clearData();
  this.diagnostics.addAll(data);
  notifyDataSetChanged();
}

如果您想使用动画或获得更好的性能,您可以使用其他 notify... 函数,而不是使用 notifyDataSetChanged()

希望这行得通...

【讨论】:

  • java.lang.NullPointerException: 尝试在空对象引用上调用虚拟方法 'boolean java.util.ArrayList.addAll(java.util.Collection)'
  • 我修复了这个错误,但我不明白如何使用 setData
  • 我修好了,但我还是不明白如何使用 setData
  • 如果你有一个新的数据列表,你可以使用函数setData()而不是创建一个新的适配器。例如,您在 createView 或任何地方使用空列表初始化适配器。当您从休息服务(或其他任何地方)获取新数据时,您只需调用adapter.setData(newlist) 而不是new Adapter(newlist)recyclerview.setAdapter(adapter)
  • 谢谢,我明白了
猜你喜欢
  • 1970-01-01
  • 2017-09-30
  • 1970-01-01
  • 2017-11-10
  • 1970-01-01
  • 2014-04-29
  • 1970-01-01
  • 2011-09-07
  • 2019-10-23
相关资源
最近更新 更多