首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >应用程序在从回收视图中删除项目时崩溃

应用程序在从回收视图中删除项目时崩溃
EN

Stack Overflow用户
提问于 2017-09-10 12:34:11
回答 3查看 3.2K关注 0票数 1

在我的应用程序中,我在回收视图中显示了一个项目列表。我已经创建了两个功能,编辑和删除每个项目在回收视图。通过这个应用程序,用户可以创建一个任务列表,可以编辑项目,也可以从回收视图中删除该项目。现在,如果我点击编辑,它是完美的工作。但是,如果我单击delete选项,应用程序就会崩溃,在adaper类中,消息数组索引会出现异常。

这是我的适配器代码。我还在代码中提到了这一行,在这里我会看到应用程序崩溃。

编辑适配器类

代码语言:javascript
复制
public class TodoAdapter extends RealmRecyclerViewAdapter<TodoModel, TodoAdapter.TaskHolder> {
    public final static String INTENT_KEY_ID = "taskId";
    public final static String INTENT_KEY_POSITION = "position";
    public final static String DATE_FORMAT = "dd/MMM/yy";


    private Realm realm;

    public interface TaskListener {

    }

    private final TaskListener taskListener;
    private final Context context;

    public TodoAdapter(TaskListener taskListener, RealmResults<TodoModel> realmResults, Context context, Realm realm) {
        super(realmResults, true);
        this.taskListener = taskListener;
        this.context = context;
        this.realm = realm;
    }

    @Override
    public TaskHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new TaskHolder( LayoutInflater.from(parent.getContext()).inflate(R.layout.todo_row, parent, false));
    }

    @Override
    public void onBindViewHolder(TaskHolder holder, final int position) {

        final TodoModel task = getData().get(position);
        holder.taskTextView.setText(task.getName());
        holder.doneCheckBox.setChecked(task.isDone());
        holder.timeTextView.setText( task.getTime() );

        final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);

        final Date date = (task.getDate());
        if (sdf.format(date).equals(sdf.format(getDate(0))))
            holder.dateTextView.setText("Today");
        else if (sdf.format(date).equals(sdf.format(getDate(-1))))
            holder.dateTextView.setText("Yesterday");
        else if (sdf.format(date).equals(sdf.format(getDate(1))))
            holder.dateTextView.setText("Tomorrow");
        else if (date.getTime() < getDate(6).getTime()) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            holder.dateTextView.setText( DateFormat.format("EEEE", calendar.getTime()).toString());
        } else
            holder.dateTextView.setText(sdf.format(task.getDate()));

        holder.cardView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(context, TodoAddActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.putExtra(INTENT_KEY_ID, getTask(position).getId());
                context.startActivity(intent);
            }
        });

        holder.doneCheckBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                TodoModel task = new TodoModel();
                task.setId(getTask(position).getId());
                task.setDate(getTask(position).getDate());
                task.setName(getTask(position).getName());
                task.setDone(((CheckBox) v).isChecked());
                updateTask(position, task);
            }
        });

        holder.deleteImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (getTask(position).isDone()) {
                    removeTask(position);
                    notifyDataSetChanged();
                    return;
                }
                AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
                alertDialog.setTitle("Confirm Delete?");
                alertDialog.setMessage("Do you want to delete the task you created?");
                alertDialog.setPositiveButton("YES", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                        removeTask(position);
                    }
                });
                alertDialog.setNegativeButton("NO", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                    }
                });
                alertDialog.show();
            }
        });
    }

    public class TaskHolder extends RecyclerView.ViewHolder {
        public CardView cardView;
        public TextView taskTextView;
        public TextView dateTextView;
        public TextView timeTextView;
        public ImageView deleteImageView;
        public CheckBox doneCheckBox;


        public TaskHolder(View itemView) {
            super(itemView);

            taskTextView = (TextView) itemView.findViewById( R.id.row_task_list_tv_name);
            dateTextView = (TextView) itemView.findViewById(R.id.row_task_list_tv_date);
            timeTextView=(TextView)itemView.findViewById( R.id.row_task_list_tv_time );
            deleteImageView = (ImageView) itemView.findViewById(R.id.row_task_list_iv_delete);
            doneCheckBox = (CheckBox) itemView.findViewById(R.id.row_task_list_cb_done);
            cardView = (CardView) itemView.findViewById(R.id.cardView);
        }
    }

    private Date getDate(int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, day);
        return calendar.getTime();
    }

    protected TodoModel getTask(int position) {
        return getData().get(position);
    }

    protected void updateTask(int position, TodoModel task) {
        realm.beginTransaction();
        TodoModel newTask = realm.where(TodoModel.class).equalTo("id", task.getId()).findFirst();
        newTask.setDate(task.getDate());
        newTask.setDone(task.isDone());
        newTask.setName(task.getName());
        realm.commitTransaction();
    }

    protected void removeTask(int position) {
        TodoModel newTask = realm.where(TodoModel.class).equalTo("id", getTask(position).getId()).findFirst();
        realm.beginTransaction();
        newTask.deleteFromRealm();
        realm.commitTransaction();
        notifyItemRemoved(position);
    }
   }

坠机报告

代码语言:javascript
复制
09-10 12:25:57.876 7332-7332/realmtest.com.to_do_list_test E/AndroidRuntime: FATAL EXCEPTION: main
                                                                         Process: realmtest.com.to_do_list_test, PID: 7332
                                                                         java.lang.ArrayIndexOutOfBoundsException: Out of range  in /Users/cm/Realm/realm-java/realm/realm-library/src/main/cpp/io_realm_internal_Collection.cpp line 133(requested: 1 valid: 1)
                                                                             at io.realm.internal.Collection.nativeGetRow(Native Method)
                                                                             at io.realm.internal.Collection.getUncheckedRow(Collection.java:386)
                                                                             at io.realm.OrderedRealmCollectionImpl.get(OrderedRealmCollectionImpl.java:106)
                                                                             at io.realm.RealmResults.get(RealmResults.java:53)
                                                                             at io.realm.OrderedRealmCollectionImpl.get(OrderedRealmCollectionImpl.java:19)
                                                                             at realmtest.com.to_do_list_test.activity.TodoAdapter.getTask(TodoAdapter.java:157)
                                                                             at realmtest.com.to_do_list_test.activity.TodoAdapter$3.onClick(TodoAdapter.java:106)
                                                                             at android.view.View.performClick(View.java:5610)
                                                                             at android.view.View$PerformClick.run(View.java:22265)
                                                                             at android.os.Handler.handleCallback(Handler.java:751)
                                                                             at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                             at android.os.Looper.loop(Looper.java:154)
                                                                             at android.app.ActivityThread.main(ActivityThread.java:6077)
                                                                             at java.lang.reflect.Method.invoke(Native Method)
                                                                             at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
                                                                             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)

getData()的实现

代码语言:javascript
复制
@Nullable
public OrderedRealmCollection<T> getData() {
    return adapterData;
}

TaskActivity类

代码语言:javascript
复制
    public class TaskActivity extends AppCompatActivity implements TodoAdapter.TaskListener{

    private static final int ADD_TASK_REQUEST_CODE = 1000;
    private static final int EDIT_TASK_REQUEST_CODE = 1001;

    private Realm realm;

    private RecyclerView recyclerView;
    private TodoAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_todo_layout);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        toolbar.setTitle("ToDo List");
        setSupportActionBar(toolbar);

        realm = Realm.getDefaultInstance();
        recyclerView =(RecyclerView)findViewById(R.id.activity_tasks_ll_task);

        setUpRecycler();

        // Variables

        // Views
        FloatingActionButton addFloatingActionButton = (FloatingActionButton) findViewById(R.id.activity_tasks_fab_add);
        //Listeners
        addFloatingActionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivityForResult(new Intent(getApplicationContext(), TodoAddActivity.class), ADD_TASK_REQUEST_CODE);
            }
        });
    }

    private void setAdapter() {
        adapter = new TodoAdapter(this, realm.where(TodoModel.class).findAll(),this,realm);
        recyclerView.setAdapter(adapter);
        adapter.notifyDataSetChanged();

    }

    private void setUpRecycler() {
        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        recyclerView.setHasFixedSize(true);
        // use a linear layout manager since the cards are vertically scrollable
        final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(layoutManager);
        setAdapter();
    }
}

image1

image2

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-09-11 10:02:11

if (getTask(position).isDone()) {中删除return语句,并将AlertDialog放在if的from子句中,如下所示。

代码语言:javascript
复制
holder.deleteImageView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (getTask(position).isDone()) {
                removeTask(position);
                notifyDataSetChanged();

            }else {
                AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
                alertDialog.setTitle("Confirm Delete?");
                alertDialog.setMessage("Do you want to delete the task you created?");
                alertDialog.setPositiveButton("YES", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                       dialog.cancel();
                       removeTask(position);
                    }
                });
                alertDialog.setNegativeButton("NO", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                       dialog.cancel();
                    }
                });
                alertDialog.show();
            }
        }
});
票数 0
EN

Stack Overflow用户

发布于 2017-09-10 12:57:55

删除条目后,您将更改适配器的列表,但没有通知适配器您已更改了列表的大小。因此,您必须告诉适配器列表的大小已经更改。

代码语言:javascript
复制
holder.deleteImageView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (getTask(position).isDone()) { //Error for this line 
            removeTask(position);
            notifyDataSetChanged(); <-------------------Add this line to your code.
            return;
        }
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
        alertDialog.setTitle("Confirm Delete?");
        alertDialog.setMessage("Do you want to delete the task you created?");
        alertDialog.setPositiveButton("YES", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
                removeTask(position);
            }
        });
        alertDialog.setNegativeButton("NO", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });
        alertDialog.show();
    }
});

每当您更改适配器列表的大小时,都必须通过调用函数notifyDataSetChanged().向适配器显式地告知适配器更改的情况。

票数 0
EN

Stack Overflow用户

发布于 2018-04-20 06:27:30

可以使用notifyDataSetChanged()

但是,如果您想要显示动画以及更新列表中的项位置

在sequest中使用此代码

notifyItemRemoved(position)

MH:用于删除项并显示动画

代码语言:javascript
复制
notifyItemRangeChanged(position, ListSize);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46140739

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档