我需要一种方法来解决以下IndexOutOfBoundsException

时间:2017-05-16 10:29:00

标签: java android list indexoutofboundsexception

我有一份清单。我为列表中的每个项目设置了cardview卡。我已经在向上滑动时实现了删除,但是当我删除最后一个项目(最后一张卡片)时,抛出了一个IndexOutOfBoundsException。 我的代码:

的活动:

public class FirstPage extends Activity
{
    RallyRestApi restApi;
    private RecyclerView recyclerView;
    private CustomAdapter adapter;
    private List<MyData> data_list;
    private Context mcontext;
    String username;
    String password;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_first_page);
        mcontext=this;
        recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        data_list = new ArrayList<>();
        load_data();
        recyclerView.setLayoutManager(new LinearLayoutManager(mcontext,LinearLayoutManager.HORIZONTAL,false));
        adapter = new CustomAdapter(FirstPage.this,data_list);
        recyclerView.setAdapter(adapter);
        username=getIntent().getStringExtra("username");
        password=getIntent().getStringExtra("password");
        ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.UP )
        {
            @Override
            public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target)
            {
                Toast.makeText(getApplicationContext(), "on Move", Toast.LENGTH_SHORT).show();
                return false;
            }

            @Override
            public void onSwiped(final RecyclerView.ViewHolder viewHolder, int swipeDir)
            {

                Toast.makeText(getApplicationContext(), "Task Status changed to COMPLETE", Toast.LENGTH_LONG).show();
                String username = getIntent().getStringExtra("username");
                String password = getIntent().getStringExtra("password");
                try
                {
                    restApi=new RallyRestApi(new URI("https://rally1.rallydev.com"),username,password);
                    JsonObject updatedValues = new JsonObject();
                    updatedValues.addProperty("State", "Completed");
                    UpdateRequest taskUpdate = new UpdateRequest(data_list.get(viewHolder.getAdapterPosition()).getRef(), updatedValues);
                    restApi.update(taskUpdate);
                    data_list.remove(viewHolder.getAdapterPosition());
                    adapter.notifyDataSetChanged();
                }
                catch (URISyntaxException | IOException e)
                {
                            e.printStackTrace();
                }
            }
        };
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
        itemTouchHelper.attachToRecyclerView(recyclerView);
    }

我的Adapter类:

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {

    private Context context;
    private List<MyData> my_data;
    FirstPage activity;
    RallyRestApi restApi;

    public CustomAdapter(FirstPage activity, List<MyData> my_data)
    {

        this.my_data = my_data;
        this.activity=activity;

    }
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.card,parent,false);
        itemView.setMinimumWidth(parent.getMeasuredWidth());
        itemView.setMinimumHeight(parent.getMeasuredHeightAndState());
        return new ViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, final int position)
    {
        holder.userstory.setText("User Story: "+my_data.get(position).getUserstory());
        holder.tasks.setText("Task: "+my_data.get(position).getTask());
        holder.seekBar.setMax(my_data.get(position).getEstimate());
        holder.seekBar.setProgress(my_data.get(position).getActual());
        holder.actual_estimate.setText(my_data.get(position).getActual()+"/"+my_data.get(position).getEstimate());
        holder.seekBar.setOnSeekBarChangeListener(new CircularSeekBar.OnCircularSeekBarChangeListener() {
            @Override
            public void onProgressChanged(CircularSeekBar circularSeekBar, int progress, boolean fromUser)
            {
//IOB exception
                holder.seekBar.setProgress(holder.seekBar.getProgress());
                holder.actual_estimate.setText(holder.seekBar.getProgress()+"/"+my_data.get(position).getEstimate());
            }

            @Override
            public void onStopTrackingTouch(CircularSeekBar seekBar)
            {
                try
                {
                    restApi=new RallyRestApi(new URI("https://rally1.rallydev.com"),activity.username,activity.password);
                    JsonObject updatedValues = new JsonObject();
                    updatedValues.addProperty("Actuals", holder.seekBar.getProgress());
                    UpdateRequest taskUpdate = new UpdateRequest(my_data.get(position).getRef(), updatedValues);
                    restApi.update(taskUpdate);
                    holder.actual_estimate.setText(holder.seekBar.getProgress()+"/"+my_data.get(position).getEstimate());
                    holder.seekBar.setProgress(holder.seekBar.getProgress());
                }
                catch (URISyntaxException | IOException e)
                {
                    e.printStackTrace();
                }
            }
            @Override
            public void onStartTrackingTouch(CircularSeekBar seekBar)
            {

            }
        });
        holder.seekBar.setProgress(holder.seekBar.getProgress());
        holder.actual_estimate.setText(holder.seekBar.getProgress()+"/"+my_data.get(position).getEstimate());
    }

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

    public  class ViewHolder extends  RecyclerView.ViewHolder
    {
        public TextView userstory,tasks,actual_estimate;
        public CircularSeekBar seekBar;
//
        public ViewHolder(View itemView)
        {
            super(itemView);
            userstory=(TextView) itemView.findViewById(R.id.tvUserStory);
            tasks=(TextView) itemView.findViewById(R.id.tvTask);
            seekBar=(CircularSeekBar) itemView.findViewById(R.id.circularSeekBar1);
            actual_estimate=(TextView) itemView.findViewById(R.id.tvactuals_estimate);
        }
    }
}

错误日志:

  

java.lang.IndexOutOfBoundsException:索引2无效,大小为2                                                                                         在   java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)                                                                                         at java.util.ArrayList.get(ArrayList.java:308)                                                                                         在   com.bmc.apetkar.akshay_rallyrest.CustomAdapter $ 1.onProgressChanged(CustomAdapter.java:68)                                                                                         在   com.circularseekbar.CircularSeekBar.setProgress(CircularSeekBar.java:530)                                                                                         在   com.bmc.apetkar.akshay_rallyrest.CustomAdapter $ 1.onProgressChanged(CustomAdapter.java:67)                                                                                         在   com.circularseekbar.CircularSeekBar.setProgress(CircularSeekBar.java:530)                                                                                         在   com.bmc.apetkar.akshay_rallyrest.CustomAdapter.onBindViewHolder(CustomAdapter.java:61)                                                                                         在   com.bmc.apetkar.akshay_rallyrest.CustomAdapter.onBindViewHolder(CustomAdapter.java:32)                                                                                         在   android.support.v7.widget.RecyclerView $ Adapter.onBindViewHolder(RecyclerView.java:5277)                                                                                         在   android.support.v7.widget.RecyclerView $ Adapter.bindViewHolder(RecyclerView.java:5310)                                                                                         在   android.support.v7.widget.RecyclerView $ Recycler.getViewForPosition(RecyclerView.java:4568)                                                                                         在   android.support.v7.widget.RecyclerView $ Recycler.getViewForPosition(RecyclerView.java:4461)                                                                                         在   android.support.v7.widget.LinearLayoutManager $ LayoutState.next(LinearLayoutManager.java:1962)                                                                                         在   android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1371)                                                                                         在   android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1334)                                                                                         在   android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:563)                                                                                         在   android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2847)                                                                                         在   android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3145)                                                                                         在android.view.View.layout(View.java:16630)                                                                                         在android.view.ViewGroup.layout(ViewGroup.java:5437)                                                                                         在android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)                                                                                         在android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)                                                                                         在android.widget.LinearLayout.onLayout(LinearLayout.java:1495)                                                                                         在android.view.View.layout(View.java:16630)                                                                                         在android.view.ViewGroup.layout(ViewGroup.java:5437)                                                                                         在android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)                                                                                         在android.widget.FrameLayout.onLayout(FrameLayout.java:273)                                                                                         在android.view.View.layout(View.java:16630)                                                                                         在android.view.ViewGroup.layout(ViewGroup.java:5437)                                                                                         在android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)                                                                                         在android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)                                                                                         在android.widget.LinearLayout.onLayout(LinearLayout.java:1495)                                                                                         在android.view.View.layout(View.java:16630)                                                                                         在android.view.ViewGroup.layout(ViewGroup.java:5437)                                                                                         在android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)                                                                                         在android.widget.FrameLayout.onLayout(FrameLayout.java:273)                                                                                         在   com.android.internal.policy.PhoneWindow $ DecorView.onLayout(PhoneWindow.java:2678)                                                                                         在android.view.View.layout(View.java:16630)                                                                                         在android.view.ViewGroup.layout(ViewGroup.java:5437)                                                                                         在android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2171)                                                                                         在android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1931)                                                                                         在android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)                                                                                         在   android.view.ViewRootImpl $ TraversalRunnable.run(ViewRootImpl.java:6013)                                                                                         在   android.view.Choreographer $ CallbackRecord.run(Choreographer.java:858)                                                                                         在android.view.Choreographer.doCallbacks(Choreographer.java:670)                                                                                         在android.view.Choreographer.doFrame(Choreographer.java:606)                                                                                         在   android.view.Choreographer $ FrameDisplayEventReceiver.run(Choreographer.java:844)                                                                                         在android.os.Handler.handleCallback(Handler.java:739)                                                                                         在android.os.Handler.dispatchMessage(Handler.java:95)                                                                                         在android.os.Looper.loop(Looper.java:148)                                                                                         在android.app.ActivityThread.main(ActivityThread.java:5417)                                                                                         at java.lang.reflect.Method.invoke(Native Method)                                                                                         在   com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:726)                                                                                         在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

我知道它可能是IndexOutOfBoundsException的副本,但是我引用它并且不明白我需要更改为position-1的位置,因为列表从0开始;

2 个答案:

答案 0 :(得分:3)

该异常源自my_data.get(position)侦听器中的onProgressChanged()

当进度发生变化时,异步调用此侦听器,但是当您执行onBindViewHolder()时,它会引用提供的原始position

因此,当您在时间X执行onBindViewHolder()时,值为2的位置有效(如果列表中至少有3个条目)。听众将保持这个值2并坚持下去。

现在,如果删除项目并且只剩下2个项目,则position = 2不再有效,但是侦听器仍然保留该值,并且在调用它时,它会尝试访问位置= 2的my_data,现在已经变得无效。

要解决此问题,您必须使侦听器保持实际数据,而不是位置。你可以这样做:

public void onBindViewHolder(final ViewHolder holder, final int position)
{
    final SomeClass data = my_data.get(position);

    holder.seekBar.setOnSeekBarChangeListener(new CircularSeekBar.OnCircularSeekBarChangeListener() {
        @Override
        public void onProgressChanged(CircularSeekBar circularSeekBar, int progress, boolean fromUser)
        {
            holder.seekBar.setProgress(holder.seekBar.getProgress());
            holder.actual_estimate.setText(holder.seekBar.getProgress()+"/" + data.getEstimate());
        }

答案 1 :(得分:0)

在删除项目之前,您可以检查列表是否已空。

if(!data_list.isEmpty()){
    data_list.remove(viewHolder.getAdapterPosition());
    adapter.notifyDataSetChanged();
}