How do I create an intent to store my object in Room?

The codelab Android Room with a View uses the following code to insert a new object:

public class NewWordActivity extends AppCompatActivity {

    public static final String EXTRA_REPLY = "com.example.android.wordlistsql.REPLY";

    private  EditText mEditWordView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_new_word);
        mEditWordView = findViewById(R.id.edit_word);

        final Button button = findViewById(R.id.button_save);
        button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                Intent replyIntent = new Intent();
                if (TextUtils.isEmpty(mEditWordView.getText())) {
                    setResult(RESULT_CANCELED, replyIntent);
                } else {
                    String word = mEditWordView.getText().toString();
                    replyIntent.putExtra(EXTRA_REPLY, word);
                    setResult(RESULT_OK, replyIntent);
                }
                finish();
            }
        });
    }
}

It’s very unclear to me how this works and where this intent gets processed. Particularly, I don’t know how do to change the function to store my own object that contains more data than just a string:

public class MyClass{
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id")
    private int id;

    @NonNull
    @ColumnInfo(name = "name")
    private String name;

    @NonNull
    @ColumnInfo(name = "description")
    private String description;

    @ColumnInfo(name = "value")
    private int value;

    ...
}

How do I create a intent to save MyClass?

Answer

First, define some entity class for your data:

@Entity(tableName = "products")
public class ProductEntity {
    @PrimaryKey
    private int id;
    private String name;
    private String description;
    private int price;

    @Override
    public int getId() {
        return id;
    }

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

    @Override
    public String getName() {
        return name;
    }

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

    @Override
    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public ProductEntity() {
    }

    public ProductEntity(int id, String name, String description, int price) {
        this.id = id;
        this.name = name;
        this.description = description;
        this.price = price;
    }    
}

Secondly, create a DAO class for it. It could be as the following:

@Dao
public interface ProductDao {
    @Query("SELECT * FROM products")
    LiveData<List<ProductEntity>> loadAllProducts();

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insertAll(List<ProductEntity> products);

    @Query("select * from products where id = :productId")
    LiveData<ProductEntity> loadProduct(int productId);

    @Query("select * from products where id = :productId")
    ProductEntity loadProductSync(int productId);
}

Then, add the info about your ProductDao to WordRoomDatabase (you can rename this class to make it to something else as it’s gonna handle not only Word objects now):

@Database(entities = {Word.class, ProductEntity.class}, version = 1)
public abstract class WordRoomDatabase extends RoomDatabase {
    ...
    public abstract ProductDao productDao();//add this os that Room generates ProductDao_Impl
    ...
}

Create a new ProductRepository specifically for your ProductEntity:

public class ProductRepository {
    private LiveData<List<ProductEntity>> mAllProducts; 

    private ProductDao mProductDao;
        WordRoomDatabase db = WordRoomDatabase.getDatabase(application);
        mProductDao = db.productDao();
        mAllProducts = mProductDao.loadAllProducts();
    }

    public LiveData<List<ProductEntity>> getAllProducts() {
        return mAllProducts;
    }  

    public void insert (ProductEntity product) {
        new insertAsyncTask(mProductDao).execute(product);
    }

    private static class insertAsyncTask extends AsyncTask<ProductEntity, Void, Void> {
        private ProductDao mProductDao;

        insertAsyncTask(ProductDao dao) {
            mProductDao = dao;
        }

        @Override
        protected Void doInBackground(final ProductEntity... params) {
            mAsyncTaskDao.insert(Arrays.asList(params[0]));
            return null;
        }
    }
}

Create ProductViewModel for your ProductEntity so that you could insert/retrieve data from your MainActivity:

public class ProductViewModel extends AndroidViewModel {

    private ProductRepository mRepository;
    private LiveData<List<ProductEntity>> mAllProducts;

    public ProductViewModel (Application application) {
        super(application);
        mRepository = new ProductRepository(application);
        mAllProducts = mRepository.getAllProducts();
    }

    LiveData<List<ProductEntity>> getAllProducts() { return mAllProducts; }

    public void insert(ProductEntity product) { mRepository.insert(product); }
}

Start your ProductActivity as below:

Intent intent = new Intent(MainActivity.this, ProductActivity.class);
startActivityForResult(intent, PRODUCT_RESULT_CODE);

You could send your ProductEntity object from ProductActivity to MainActivity in the following way:

//product is set by you somewhere
Intent replyIntent = new Intent();
replyIntent.putExtra(EXTRA_REPLY, product);
setResult(RESULT_OK, replyIntent);

Then, handle it in MainActivity via onActivityResult and save the product using productViewModel:

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == NEW_WORD_ACTIVITY_REQUEST_CODE && resultCode == RESULT_OK) {
        Word word = new Word(data.getStringExtra(NewWordActivity.EXTRA_REPLY));
        mWordViewModel.insert(word);
    } else if (requestCode == PRODUCT_RESULT_CODE && resultCode == RESULT_OK) {
        ProductEntity product = (ProductEntity) data.getSerializableExtra(NewWordActivity.EXTRA_MYCLASS_REPLY);  
        productViewModel.insert(product);            
    } else {
        Toast.makeText(
                getApplicationContext(),
                R.string.empty_not_saved,
                Toast.LENGTH_LONG).show();
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *