mardi 26 avril 2016

How to save state of checkbox in android app

I have an app that stores cards and later asks the user to fill-in the blank a random word taken from the card. The list of cards is stored in a RecyclerView. After the user selects the checkbox, the description of that card is extracted and set as the string the user will have to fill-in the blank. I already have a checkbox implemented in the layout and an action that is performed after the checkbox is selected. Now, I want to save the state of the checkbox and the description extracted so that when the user exits the app and comes back, the list will show what card was selected and the right description to fill in will come up. I have a CardStorage class that uses sharedpreferences, but when I try to save the checkbox status and the description extracted, the app crashes. Should I create a new Storage class? Or should I modify the toJson method in the Card class and add a new method in the CardStorage class? Thanks!

Card class:

public class Card implements Comparable, Parcelable{

public int id;
public String title;
public String description;
boolean isSelected;
public static String descriptionSelected;

public Card(){}

protected Card(Parcel in){
    id = in.readInt();
    title = in.readString();
    description = in.readString();
}

private Card(String title, String description){
    this.title = title;
    this.description = description;
}


public static final Parcelable.Creator<Card> CREATOR = new Parcelable.Creator<Card>() {
    @Override
    public Card createFromParcel(Parcel in) {
        return new Card(in);
    }

    @Override
    public Card[] newArray(int size) {
        return new Card[size];
    }
};

@Override
public int describeContents() {return 0;}

@Override
public void writeToParcel (Parcel parcel, int i) {
    parcel.writeInt(id);
    parcel.writeString(title);
    parcel.writeString(description);
}

public String toJson() {
    JSONObject jsonObject = new JSONObject();
    try {
        jsonObject.put("id", id);
        jsonObject.put("title", title);
        jsonObject.put("description", description);
    } catch (JSONException e) {
        throw new IllegalStateException("Failed to convert the object to JSON");
    }
    return jsonObject.toString();
}

public static Card fromJson(String string) {
    JSONObject jsonObject;
    Card card = new Card();
    try {
        jsonObject = new JSONObject(string);
        card.id = jsonObject.getInt("id");
        card.title = jsonObject.getString("title");
        card.description = jsonObject.getString("description");
    } catch (JSONException e) {
        throw new IllegalArgumentException("Failed to parse the String: " + string);
    }

    return card;
}

@Override
public String toString() {
    return "Card{" +
            "id" + id +
            "title=" + title +
            ", description=" + description +
            '}';
}

@Override
public boolean equals(Object o) {
    if (this == o) {
        return true;
    }
    if (!(o instanceof Card)) {
        return false;
    }
    Card card = (Card) o;
    return id==card.id &&
            title.equals(card.title) &&
            description.equals(card.description);

}

@Override
@TargetApi(21)
public int hashCode() {
    return Objects.hash(id, title, description);
}

@Override
public int compareTo(@NonNull Card other) {
    Card card = new Card(title,description);

    return card.title.compareToIgnoreCase(other.title);

}

public boolean isSelected() {
    return isSelected;
}

public void setSelected(boolean isSelected) {
    this.isSelected = isSelected;
}

public void changeDescriptionSelected (String descriptionSelected){
    if(isSelected()){
        this.descriptionSelected = descriptionSelected;
    }
    else this.descriptionSelected = "You haven't selected anything";

}

}

Card adapter class:

public class CardAdapter extends RecyclerView.Adapter {

private SortedList<Card> mCardList;
private CardStorage mCardStorage;
private Context mContext;

public CardAdapter(Context context, Set<Card> cards) {
    mCardList = new SortedList<Card>(Card.class, new SortedListCallback());
    mCardList.addAll(cards);
    mCardStorage = new CardStorage(context);
    mContext = context;
}


@Override
public CardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.card_row, parent, false);
    return new CardViewHolder(v);
}

@Override
public void onBindViewHolder(final CardViewHolder cardViewHolder, final int position) {


    cardViewHolder.mCardTitle.setText(mCardList.get(position).title);
    cardViewHolder.mCardDescription.setText(mCardList.get(position).description);

    cardViewHolder.mCheckBox.setChecked(mCardList.get(position).isSelected());
    cardViewHolder.mCheckBox.setTag(mCardList.get(position));



    cardViewHolder.mCheckBox.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {
           CheckBox cb = (CheckBox) view;
            Card card = (Card) cb.getTag();
            card.setSelected(cb.isChecked());
            card.changeDescriptionSelected(card.description);
            if (cb.isChecked()) {
                Toast.makeText(mContext, "Only the last card selected will count", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(mContext, "Select another card", Toast.LENGTH_SHORT).show();
            }
        }

    });


    cardViewHolder.mDeleteImageView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Card toBeDeleted = mCardList.get(position);
            mCardList.removeItemAt(position);
            mCardStorage.deleteCard(toBeDeleted);
            notifyDataSetChanged();
            Toast.makeText(mContext, mContext.getString(R.string.card_deleted,
                    toBeDeleted.title), Toast.LENGTH_SHORT).show();
        }
    });
}



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


public void addCard(Card card) {
    mCardList.add(card);
    notifyDataSetChanged();
}


public static class CardViewHolder extends RecyclerView.ViewHolder {
    private TextView mCardTitle;
    private TextView mCardDescription;
    private ImageView mDeleteImageView;
    private CheckBox mCheckBox;


    CardViewHolder(View itemView) {
        super(itemView);
        mCardTitle = (TextView) itemView.findViewById(R.id.text_card_title);
        mCardDescription = (TextView) itemView.findViewById(R.id.text_card_description);
        mDeleteImageView = (ImageView) itemView.findViewById(R.id.image_delete_card);
        mCheckBox = (CheckBox) itemView.findViewById(R.id.checkBox);
    }
}

private static class SortedListCallback extends SortedList.Callback<Card>{
    @Override
    public int compare(Card o1, Card o2) {
        return o1.compareTo(o2);
    }

    @Override
    public void onInserted(int position, int count) {
        //No op
    }

    @Override
    public void onRemoved(int position, int count) {
        //No op
    }

    @Override
    public void onMoved(int fromPosition, int toPosition) {
        //No op
    }

    @Override
    public void onChanged(int position, int count) {
        //No op
    }

    @Override
    public boolean areContentsTheSame(Card oldItem, Card newItem) {
        return oldItem.equals(newItem);
    }

    @Override
    public boolean areItemsTheSame(Card item1, Card item2) {
        return item1.equals(item2);
    }
}

@TargetApi(21)
public static class DividerItemDecoration extends RecyclerView.ItemDecoration {

    private Drawable mDivider;

    public DividerItemDecoration(Context context) {
        mDivider = context.getDrawable(R.drawable.divider);
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        int left = parent.getPaddingLeft();
        int right = parent.getWidth() - parent.getPaddingRight();
        for (int i = 0; i < parent.getChildCount(); i++) {
            View child = parent.getChildAt(i);
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            int top = child.getBottom() + params.bottomMargin;
            int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }
}

}

Card Storage :

public class CardStorage {

private static final String TAG = CardStorage.class.getSimpleName();
private static final String CARD_PREFERENCES_NAME = "card_preferences";
private static final SecureRandom SECURE_RANDOM = new SecureRandom();

public SharedPreferences mSharedPreferences;

public CardStorage(Context context) {
    Context storageContext = context;
    mSharedPreferences = storageContext.getSharedPreferences(CARD_PREFERENCES_NAME,Context.MODE_PRIVATE);

}

public Card saveCard(String title, String description){
    Card card = new Card();
    card.id = SECURE_RANDOM.nextInt();
    card.title = title;
    card.description = description;
    SharedPreferences.Editor editor = mSharedPreferences.edit();
    editor.putString(String.valueOf(card.id), card.toJson());
    editor.apply();
    return card;
}

public Set<Card> getCards(){
    Set<Card> cards = new HashSet<>();
    for(Map.Entry<String, ?> entry : mSharedPreferences.getAll().entrySet()){
        cards.add(Card.fromJson(entry.getValue().toString()));
    }
    return cards;
}

public void deleteCard (Card toBeDeleted) {
    for (Map.Entry<String, ?> entry : mSharedPreferences.getAll().entrySet()) {
        Card card = Card.fromJson(entry.getValue().toString());
        if (card.id == toBeDeleted.id){
            SharedPreferences.Editor editor = mSharedPreferences.edit();
            editor.remove(String.valueOf(card.id));
            editor.apply();
            return;
        }
    }
}

}

Thanks!




Aucun commentaire:

Enregistrer un commentaire