11

I want to pass a realm object from one activity to another. e.g.

Intent intent = new Intent(MainActivity.this, Second.class);
intent.putExtra("Student", studentObj); // studentObj is a realm object
startActivity(intent);

And receive it from the Second activity

Intent i = getIntent();
student = (Student) i.getSerializableExtra("Student");

but this causes a null pointer exception.

java.lang.RuntimeException: Unable to start activity ComponentInfo{testapp.com.tms/tms.testapp.com.tms.view.SecondActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'io.realm.internal.LinkView io.realm.internal.Row.getLinkList(long)' on a null object reference
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2693)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2760)
            at android.app.ActivityThread.access$900(ActivityThread.java:177)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1448)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:145)
            at android.app.ActivityThread.main(ActivityThread.java:5944)
            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:1389)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1184)

Any idea to fix this?

Ezio
  • 121
  • 1
  • 7

4 Answers4

12

Realm currently doesn't support parsing RealmObjects across Intents natively. So you have 2 options :

  1. Send some identifier instead and requery for the object on the other side.

  2. Use a 3rd party library like Parceler. You can see how here: https://realm.io/docs/java/latest/#parceler

Maelig
  • 2,046
  • 4
  • 24
  • 49
Christian Melchior
  • 19,978
  • 5
  • 62
  • 53
1

I have the some problem when I tried to pass realmobject to another activity. So, I created a DTO object based in my model, and this one implements Parcelable. Its works, but I know that isn't the better way.

See the implementation:

I have two entities, Student and Disciplines, as code below.

package turbiani.com.br.realmfordummiesandroid.model;

import android.os.Parcel;
import android.os.Parcelable;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Random;
import java.util.UUID;

import io.realm.RealmList;
import io.realm.RealmObject;
import io.realm.annotations.Ignore;
import io.realm.annotations.PrimaryKey;

/**
 * Created by turbiani on 23/07/15.
 */
public class Student extends RealmObject  {

    @PrimaryKey
    private int id;
    private String name;
    private RealmList<Discipline> disciplines;

    public Student(){
        this.id = new Random().nextInt(Integer.MAX_VALUE);
    }

    public Student(String name, RealmList<Discipline> disciplines) {
        this.name = name;
        this.disciplines = disciplines;
        this.id = new Random().nextInt(Integer.MAX_VALUE);
    }

    private Student(Parcel p){
        this.name = p.readString();
        this.disciplines = new RealmList<Discipline>();
        this.id = p.readInt();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public RealmList<Discipline> getDisciplines() {
        return disciplines;
    }

    public void setDisciplines(RealmList<Discipline> disciplines) {
        this.disciplines = disciplines;
    }

    public int getId() {
        return id;
    }

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

}

And Discipline class.

package turbiani.com.br.realmfordummiesandroid.model;

import android.os.Parcel;
import android.os.Parcelable;

import java.io.Serializable;

import io.realm.RealmObject;

/**
 * Created by turbiani on 23/07/15.
 */
public class Discipline extends RealmObject {


    private String name;
    private String grade;
    private int    studentId;

    public Discipline(){}

    public Discipline(String name, String grade, int studentId) {
        this.name = name;
        this.grade = grade;
        this.studentId = studentId;
    }

    private Discipline(Parcel p){
        this.name       = p.readString();
        this.grade      = p.readString();
        this.studentId  = p.readInt();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }

    public int getStudentId() {
        return studentId;
    }

    public void setStudentId(int studentId) {
        this.studentId = studentId;
    }

}

StudentDTO and DisciplineDTO implements Parcelable.

package turbiani.com.br.realmfordummiesandroid.dto;

import android.os.Parcel;
import android.os.Parcelable;

import java.util.ArrayList;
import java.util.List;

import turbiani.com.br.realmfordummiesandroid.model.Discipline;

/**
 * Created by turbiani on 04/08/15.
 */
public class StudentDTO implements Parcelable{

    private int studentId;
    private String studentName;
    private List<DisciplineDTO> studentDisciplines;

    public StudentDTO(){}

    private StudentDTO(Parcel p){
        this.studentName = p.readString();
        this.studentDisciplines = new ArrayList<DisciplineDTO>();
        p.readTypedList(this.studentDisciplines, DisciplineDTO.CREATOR);
        this.studentId = p.readInt();
    }

    public String getStudentName() {
        return studentName;
    }

    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }

    public List<DisciplineDTO> getStudentDisciplines() {
        return studentDisciplines;
    }

    public void setStudentDisciplines(List<DisciplineDTO> studentDisciplines) {
        this.studentDisciplines = studentDisciplines;
    }

    public int getStudentId() {
        return studentId;
    }

    public void setStudentId(int studentId) {
        this.studentId = studentId;
    }

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

        public StudentDTO[] newArray(int size){
            return new StudentDTO[size];
        }
    };

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(studentName);
        dest.writeTypedList(studentDisciplines);
        dest.writeInt(studentId);
    }
}


package turbiani.com.br.realmfordummiesandroid.dto;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Created by turbiani on 04/08/15.
 */
public class DisciplineDTO implements Parcelable {

    private String disciplineName;
    private String disciplineGrade;
    private int    studentId;

    public DisciplineDTO(){}

    private DisciplineDTO(Parcel p){
        this.disciplineName     = p.readString();
        this.disciplineGrade    = p.readString();
        this.studentId          = p.readInt();
    }

    public String getDisciplineName() {
        return disciplineName;
    }

    public void setDisciplineName(String disciplineName) {
        this.disciplineName = disciplineName;
    }

    public String getDisciplineGrade() {

        return disciplineGrade;
    }

    public void setDisciplineGrade(String disciplineGrade) {
        this.disciplineGrade = disciplineGrade;
    }

    public int getStudentId() {
        return studentId;
    }

    public void setStudentId(int studentId) {
        this.studentId = studentId;
    }
goes to
    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(disciplineName);
        dest.writeString(disciplineGrade);
        dest.writeInt(studentId);
    }

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

        public DisciplineDTO[] newArray(int size){
            return new DisciplineDTO[size];
        }
    };

}

Finally, how i use this in my activity.

studentList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                StudentAdapter adapter = new StudentAdapter();
                Intent intent = new Intent(MainActivity.this, AddDiscipline.class);
                intent.putExtra("StudentDTO", adapter.adaptToStudentDTO(students.get(position)));
                startActivity(intent);
            }
        });

In AddDiscipline activity I get dto object.

@Override
    public void onResume() {
        super.onResume();
        studentDisciplineList           = (ListView) findViewById(R.id.studentDisciplineList);
        btnAddDiscipline                = (Button) findViewById(R.id.btnAddDiscipline);
        final EditText disciplineName   = (EditText) findViewById(R.id.txtDisciplineName);
        final EditText disciplineGrade  = (EditText) findViewById(R.id.txtGrade);

        this.studentDTO = getIntent().getParcelableExtra("StudentDTO");
        studentDisciplineList.setAdapter(getAdapterToStudentDisciplineList());

If you want the complete source code, get in https://github.com/Turbiani/RealmForDummiesAndroid

0

Your ROW object is null on which you are calling getLinkList(long).

Check whether ROW is serialized or not ? Probably it's not.

Neeraj Kumar
  • 943
  • 4
  • 16
0

Sending objects directly through the intent may cause issues since they will all have to oblige to the parcellable or serializable contract. Another alternative to this will be to pass the key or Id of the Object in the intent rather than the entire object.

Realm in the recent versions that I have used has an ObjectId property type to denote keys that can be used for this purpose.

Example:

class Habit: RealmObject {
    @PrimaryKey
    var _id: ObjectId = ObjectId.create()

    var name = ""

}

and then while sending the _id you can convert it to the string

Intent intent = new Intent(MainActivity.this, AddDiscipline.class);
intent.putExtra("StudentDTO_Id", students.get(position)._id.toString());
startActivity(intent);

and parse it while receiving.


var id = ObjectId.from(intent.getStringExtra("StudentDTO_Id"))

Bawender Yandra
  • 200
  • 1
  • 9