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(); } }