samedi 5 décembre 2015

RecyclerView with SQLite data crashes due to incorrect index

I have a recyclerView which populates with data from an SQLite database. Each item has a button which can remove its flag in the database and thus disappear from the recyclerView list.

The problem I get is when I try to remove items in different orders, the app crashes and cites an incorrect/unknown index as the cause.

Here is the (partial) code for my recyclerView where I think the problem lies:

@Override
    public BookmarksDetailRecycleAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                                       int viewType) {
        // create a new view
        View itemLayoutView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.dua_detail_item_card, null);

        // create ViewHolder
        mHolder = new ViewHolder(itemLayoutView);
        return mHolder;
    }

    public void deleteRow(int position){
        mDuaData.remove(position); // this will remove row of data
        notifyItemRemoved(position); // this will do the animation of removal
        notifyItemRangeChanged(position, mDuaData.size()); // From GreenTech email
        // dataSetChanged();
    }

    @UiThread
    protected void dataSetChanged() {
        notifyDataSetChanged();
    }

    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(ViewHolder mHolder, int position){//final RecyclerView rv) {
        // - get data from your itemsData at this position
        // - replace the contents of the view with that itemsData
        final int finalPosition = position;

        mHolder.tvDuaNumber.setText(mDuaData.get(position).getReference() + "");
        mHolder.tvDuaArabic.setText(Html.fromHtml(mDuaData.get(position).getArabic()));

        final Spannable translation = new SpannableString(mDuaData.get(position).getTranslation());
        mHolder.tvDuaTranslation.setText(translation);

        if (mDuaData.get(position).getBook_reference() != null)
            mHolder.tvDuaReference.setText(Html.fromHtml(mDuaData.get(position).getBook_reference()));
        else
            mHolder.tvDuaReference.setText("null");

        if (mDuaData.get(position).getFav()) {
            mHolder.favButton.setText("{faw-star}");
        } else {
            mHolder.favButton.setText("{faw-star-o}");
        }

        final ViewHolder finalmHolder = mHolder;

        mHolder.shareButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View convertView) {
                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_SEND);
                intent.putExtra(Intent.EXTRA_TEXT,
                        myToolbarTitle + "\n\n" +
                                finalmHolder.tvDuaArabic.getText() + "\n\n" +
                                finalmHolder.tvDuaTranslation.getText() + "\n\n" +
                                finalmHolder.tvDuaReference.getText() + "\n\n" +
                                convertView.getResources().getString(R.string.action_share_credit)
                );
                intent.setType("text/plain");
                convertView.getContext().startActivity(
                        Intent.createChooser(
                                intent,
                                convertView.getResources().getString(R.string.action_share_title)
                        )
                );
            }
        });

        finalmHolder.favButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                boolean isFav = false;
                Log.d("K12_isFav", "isFav: " + isFav);

                int sql_position = Integer.parseInt(finalmHolder.tvDuaNumber.getText().toString());                

                Log.d("K12_sqlPosition", sql_position + "");

                deleteRow(finalPosition);

                Resources resources = v.getResources();
                String snack_begin = resources.getString(R.string.snackbar_text_begin);
                String snack_end = resources.getString(R.string.snackbar_text_end);
                String snack_action = resources.getString(R.string.snackbar_action).toUpperCase();

                // Following snippet taken from:
                // http://ift.tt/1NAZXQw
                mDbHelper = new ExternalDbOpenHelper(v.getContext().getApplicationContext());

                SQLiteDatabase db = mDbHelper.getReadableDatabase();

                // New value for one column
                ContentValues values = new ContentValues();
                values.put(HisnDatabaseInfo.DuaTable.FAV, isFav);

                // Which row to update, based on the ID
                String selection = HisnDatabaseInfo.DuaTable.DUA_ID + " LIKE ?";
                String[] selectionArgs = {String.valueOf(finalmHolder.tvDuaNumber.getText().toString())};
                Log.d("K12_selectionArgs", "tvDuaNumber: " + String.valueOf(finalmHolder.tvDuaNumber.getText().toString()));

                int count = db.update(
                        HisnDatabaseInfo.DuaTable.TABLE_NAME,
                        values,
                        selection,
                        selectionArgs);

                if (count == 1) {
                    if (isFav) {
                        finalmHolder.favButton.setText("{faw-star}");
                    } else {
                        finalmHolder.favButton.setText("{faw-star-o}");                    
                    }                    
                }
                if (getItemCount() == 0) {
                    // I don't even know if this block is needed. Review once you have some sleep.
                }
            }
        });
    }

    // inner class to hold a reference to each item of RecyclerView
    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView tvDuaNumber;
        public TextView tvDuaArabic;
        public TextView tvDuaTranslation;
        public TextView tvDuaReference;
        public IconicsButton shareButton;
        public IconicsButton favButton;

        public ViewHolder(View itemLayoutView) {
            super(itemLayoutView);
            tvDuaNumber = (TextView) itemLayoutView.findViewById(R.id.txtDuaNumber);
            tvDuaArabic = (TextView) itemLayoutView.findViewById(R.id.txtDuaArabic);
            tvDuaTranslation = (TextView) itemLayoutView.findViewById(R.id.txtDuaTranslation);
            tvDuaReference = (TextView) itemLayoutView.findViewById(R.id.txtDuaReference);
            shareButton = (IconicsButton) itemLayoutView.findViewById(R.id.button_share);
            favButton = (IconicsButton) itemLayoutView.findViewById(R.id.button_star);

            tvDuaArabic.setTypeface(sCachedTypeface);
            tvDuaArabic.setTextSize(prefArabicFontSize);
            tvDuaTranslation.setTextSize(prefOtherFontSize);
            tvDuaReference.setTextSize(prefOtherFontSize);
        }
    }

    // Return the size of your itemsData (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return mDuaData == null ? 0 : mDuaData.size();
    }

The full code for the adapter can be viewed on Github.

I have been trying to solve this for a while but I can't really see what the problem is. Will appreciate any help.

Thanks.

Aucun commentaire:

Enregistrer un commentaire