Search code examples
androidsqliteandroid-recyclerviewcursor

Pass data from recyclerview to activity with a cursor


i've got an application with a recyclervView which get data from SQLite database with a cursor. Now, i want to pass these datas to another activity when we click on an item. It is possible to pass datas with cursor ? And get the id of the row to identify data in database ?

Second question, which is the better solution for the itemOnClick method ? Where i use this method (in the viewHolder class? Or in the onBindValue ?) What i need to put in the putExtra method ? My cursor ?

My code of adapter and holder is below if that can help :

public class GroceryAdapter extends RecyclerView.Adapter<GroceryAdapter.GroceryViewHolder> implements View.OnClickListener {

    private Context mContext;
    private Cursor mCursor;
    int id;


    public GroceryAdapter(Context context,Cursor cursor){
        mContext = context;
        mCursor = cursor;
    }

    @Override
    public void onClick(View v) {
    }

    public class GroceryViewHolder extends RecyclerView.ViewHolder{
        public TextView dateItem, colorItem, textItem;
        public ToggleButton lucidItem;


        public GroceryViewHolder(final View itemView) {
            super(itemView);
            dateItem = itemView.findViewById(R.id.date_item);
            colorItem = itemView.findViewById(R.id.color_item);
            textItem = itemView.findViewById(R.id.text_item);
            lucidItem = itemView.findViewById(R.id.lucid_item);

        }


    }

    @NonNull
    @Override
    public GroceryViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(mContext);
        View view = inflater.inflate(R.layout.grocery_item, parent, false);
        return new GroceryViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull GroceryViewHolder holder, int position) {
        if(!mCursor.moveToPosition(position)){
            return;
        }
        final int id = mCursor.getInt(mCursor.getColumnIndex(CarnetDAO.ID_CARNET));
        String text = mCursor.getString(mCursor.getColumnIndex(CarnetDAO.TEXTE_CARNET));
        int color = mCursor.getInt(mCursor.getColumnIndex(CarnetDAO.COULEUR_CARNET));
        String date = mCursor.getString(mCursor.getColumnIndex(CarnetDAO.DATE_CARNET));
        int lucide = mCursor.getInt(mCursor.getColumnIndex(CarnetDAO.LUCIDITE_CARNET));

        holder.dateItem.setText(date);
        holder.colorItem.setBackgroundColor(color);
        holder.textItem.setText(text);

        if(lucide == 1){
            holder.lucidItem.setVisibility(View.VISIBLE);
        }
    }



    @Override
    public int getItemCount() {
        return mCursor.getCount();
    }

    public void swapCursor(Cursor newCursor){
        if(mCursor != null){
            mCursor.close();
        }
        mCursor = newCursor;
        if(newCursor != null){
            notifyDataSetChanged();
        }
    }

}

My data model :

public class Carnet {

public Carnet(){
    super();
}

private int id;
private String text;
private String userId;
private int color;
private String method;
private String date;
private int lucid;


public int getId(){
    return id;
}

public void setId(int id){
    this.id = id;
}

public String getText(){
    return text;
}

public void setText(String text){
    this.text = text;
}

public int getLucid(){
    return lucid;
}

public void setLucid(int lucid){
    this.lucid = lucid;
}

public void setMethod(String method){
    this.method = method;
}

public String getMethod(){
    return method;
}

public void setDate(String date){
    this.date = date;
}

public String getDate(){
    return date;
}

public void setColor(int color){
    this.color = color;
}

public  int getColor(){
    return color;
}

}

I saw Parcelable but i don't know how to use it and what is the speciality of this.

EDIT

I tried to catch my intent in the new activity but application crashed. I got this error :

FATAL EXCEPTION: main Process: morpheus.oniri, PID: 6696 java.lang.RuntimeException: Unable to start activity ComponentInfo{morpheus.oniri/morpheus.oniri.activities.afficherCarnetActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.isEmpty()' on a null object reference at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387) at android.app.ActivityThread.access$800(ActivityThread.java:151) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5254) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.isEmpty()' on a null object reference at morpheus.oniri.activities.afficherCarnetActivity.getAllData(afficherCarnetActivity.java:113) at morpheus.oniri.activities.afficherCarnetActivity.onCreate(afficherCarnetActivity.java:107) at android.app.Activity.performCreate(Activity.java:5990) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)  at android.app.ActivityThread.access$800(ActivityThread.java:151)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)  at android.os.Handler.dispatchMessage(Handler.java:102)  at android.os.Looper.loop(Looper.java:135)  at android.app.ActivityThread.main(ActivityThread.java:5254)  at java.lang.reflect.Method.invoke(Native Method)  at java.lang.reflect.Method.invoke(Method.java:372)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

I did this in the onCreate().

Intent i = getIntent();
Carnet carnetP;
carnetP = i.getParcelableExtra("data");
notes = carnetP.getText();

The error is on this line, in my method getAllData() called in the onCreate()

if(!notes.isEmpty()){
    dream.setVisibility(View.VISIBLE);
    getDream.setChecked(true);
    getDream.setBackgroundResource(R.color.colorLog);
} else{
    dream.setVisibility(View.GONE);
    getDream.setChecked(false);
    getDream.setBackgroundResource(R.color.colorText);
}

Effectively, when i do a Log.d() my String variable "notes" is null but if I i do a Log.d() on "carnetP" i've got this

morpheus.oniri.model.Carnet@14dbb242 And this is not what is stored in my database.

I did my putExtra on click like this

public class GroceryViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ public TextView dateItem, colorItem, textItem; public ToggleButton lucidItem;

public GroceryViewHolder(final View itemView) {
    super(itemView);
    dateItem = itemView.findViewById(R.id.date_item);
    colorItem = itemView.findViewById(R.id.color_item);
    textItem = itemView.findViewById(R.id.text_item);
    lucidItem = itemView.findViewById(R.id.lucid_item);


    itemView.setOnClickListener(this); //my itemView clik
}


@Override
public void onClick(View v) {
    int pos = getAdapterPosition();
    if(pos != RecyclerView.NO_POSITION){
        Intent intent = new Intent(mContext, afficherCarnetActivity.class);
        intent.putExtra("data", new Carnet());
        mContext.startActivity(intent);
    }

}

}


Solution

  • This is Parcelable class :

    public class Camel implements Parcelable {
    private int id;
    private String text;
    private String userId;
    private int color;
    private String method;
    private String date;
    private int lucid;
    
    @Override
    public int describeContents() {
        return 0;
    }
    
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(this.id);
        dest.writeString(this.text);
        dest.writeString(this.userId);
        dest.writeInt(this.color);
        dest.writeString(this.method);
        dest.writeString(this.date);
        dest.writeInt(this.lucid);
    }
    
    public Camel() {
    }
    
    protected Camel(Parcel in) {
        this.id = in.readInt();
        this.text = in.readString();
        this.userId = in.readString();
        this.color = in.readInt();
        this.method = in.readString();
        this.date = in.readString();
        this.lucid = in.readInt();
    }
    
    public static final Parcelable.Creator<Camel> CREATOR = new Parcelable.Creator<Camel>() {
        @Override
        public Camel createFromParcel(Parcel source) {
            return new Camel(source);
        }
    
        @Override
        public Camel[] newArray(int size) {
            return new Camel[size];
        }
    };
    }
    

    Now you pass object of this class to second activity.

    intent.putExtra("key",carnetdata );
    

    Not let's discuss about you NPE error.

    This error come because you pass new Object of Camel class which have null value of all fields .You should be pass object which item clicked.

    public class GroceryAdapter extends RecyclerView.Adapter<GroceryAdapter.GroceryViewHolder> implements View.OnClickListener {
    
    private Context mContext;
    private Cursor mCursor;
    List<Carnet> mListCarnet;
    int id;
    
    
    public GroceryAdapter(Context context,Cursor cursor){
        mContext = context;
        mCursor = cursor;
        mListCarnet=new ArrayList<>();
    }
    
    @Override
    public void onClick(View v) {
    
    int pos = getAdapterPosition();
        if(pos != RecyclerView.NO_POSITION){
        Intent intent = new Intent(mContext, afficherCarnetActivity.class);
        intent.putExtra("data", mListCarnet.get(pos));
        mContext.startActivity(intent);
        }
    }
    
    public class GroceryViewHolder extends RecyclerView.ViewHolder{
        public TextView dateItem, colorItem, textItem;
        public ToggleButton lucidItem;
    
    
        public GroceryViewHolder(final View itemView) {
            super(itemView);
            dateItem = itemView.findViewById(R.id.date_item);
            colorItem = itemView.findViewById(R.id.color_item);
            textItem = itemView.findViewById(R.id.text_item);
            lucidItem = itemView.findViewById(R.id.lucid_item);
    
            itemView.setOnClickListener(this); 
        }
    
    
    }
    
    @NonNull
    @Override
    public GroceryViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(mContext);
        View view = inflater.inflate(R.layout.grocery_item, parent, false);
        return new GroceryViewHolder(view);
    }
    
    @Override
    public void onBindViewHolder(@NonNull GroceryViewHolder holder, int position) {
        if(!mCursor.moveToPosition(position)){
            return;
        }
        final int id = mCursor.getInt(mCursor.getColumnIndex(CarnetDAO.ID_CARNET));
        String text = mCursor.getString(mCursor.getColumnIndex(CarnetDAO.TEXTE_CARNET));
        int color = mCursor.getInt(mCursor.getColumnIndex(CarnetDAO.COULEUR_CARNET));
        String date = mCursor.getString(mCursor.getColumnIndex(CarnetDAO.DATE_CARNET));
        int lucide = mCursor.getInt(mCursor.getColumnIndex(CarnetDAO.LUCIDITE_CARNET));
    
        holder.dateItem.setText(date);
        holder.colorItem.setBackgroundColor(color);
        holder.textItem.setText(text);
    
    
        Carnet carnet=new Carnet();
        carnet.setId(id);
        carnet.setText(text);
        carnet.setColor(color);
        carnet.setDate(date);
        carnet.setLucide.(lucide);
        mListCarnet.add(carnet);
    
        if(lucide == 1){
            holder.lucidItem.setVisibility(View.VISIBLE);
        }
    }
    
    
    
    @Override
    public int getItemCount() {
        return mCursor.getCount();
    }
    
    public void swapCursor(Cursor newCursor){
        if(mCursor != null){
            mCursor.close();
        }
        mCursor = newCursor;
        if(newCursor != null){
            notifyDataSetChanged();
        }
    }
    

    }