Room: Retrieving the user info by using ID - android

I want to have the info of a member passed to the second activity.
This is the code in the first activity.
public void onMemberClick(int position) {
Member member = mMember.get(position);
Intent intent = new Intent(getApplicationContext(),MemberInfo.class);
intent.putExtra("MemberID", member.getId());
MemberInfo.open(this, member.getId());
This is the code in the second activity.
public static void open(Activity activity, long memberid) {
Intent intent = new Intent(activity, MemberInfo.class);
intent.putExtra("MemberID", memberid);
activity.startActivity(intent);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_memberinfo);
Intent intent = getIntent();
if (intent != null && intent.hasExtra("MemberID")) {
long memberid = intent.getLongExtra("MemberID", -1);
// TODO: get customer details based on customer id
TextView firstname = findViewById(R.id.layout_memberfirstname);
TextView surname = findViewById(R.id.layout_membersurname);
TextView balance = findViewById(R.id.layout_memberbalance);
}
else {
Toast.makeText(
getApplicationContext(),
R.string.empty_not_saved,
Toast.LENGTH_LONG).show();
}
So in the first activity, I got a list with members. I click on a member and I want to have the ID of the member passed through the open method. The ID should be passed to the second activity.
A member has a first name, surname and balance. I want to get those details shown in the Textviews. How can I get those information by using the ID of that member?

Try this.
Java:
#Query("select * from user where id= :id")
User getUserById(Long id);
Kotlin:
#Query("select * from user where id= :id")
fun getUserById(id: Long) : User
Hope this helps

Query to get member list
#Query("SELECT firstname, surname FROM Member WHERE user IN (:users)")
public List<Member> Memberlist(List<String> members);

make query like below into dao interface in room db..
#Query("SELECT * FROM TableName WHERE id=:id")
User getUserData(long id);
create app level activity..
public class AppActivity extends Application {
static AppDatabase db;
#Override
public void onCreate() {
super.onCreate();
db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "database-name").build();
}
public static AppDatabase getDatabase() {
return db;
}
}
this activity define into android manifest file in application tag..
android:name=".db.AppActivity" // this line add into application tag.
after that define db version and other things..
#Database(entities = {MyTable.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract MyTableDao getTableDao();
}
after that in second activity getting member id then perform above query like below..
Member member=AppActivity.getDatabase().getTableDao().getData(memberId);
make sure table has data and member id not null.
after you want show all details without factching data then pass all data into intent and get data using intent.

I had to create a new method in my DAO. This query did the trick: SELECT * FROM member_table WHERE MemberID=:id
This query then should return a object of the class you try to get, in my case:
Member getInfo(long id);

Related

How to retrieve data from Room SQLite database?

So I have created a room database following tutorials on youtube. I have two columns day and likes, each holding int's. Currently I have populated the database manually with three rows of data.
Here is the code for populating database manually:
#Database(entities = Recovery.class, version = 1, exportSchema = false)
public abstract class RecoveryDatabase extends RoomDatabase {
private static RecoveryDatabase INSTANCE;
public abstract RecoveryDao recoveryDao();
// Singleton
public static RecoveryDatabase getInstance(final Context context) {
if (INSTANCE == null) {
synchronized (RecoveryDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(), RecoveryDatabase.class, "recovery_database").fallbackToDestructiveMigration().addCallback(roomCallback).build();
}
}
}
return INSTANCE;
}
private static RecoveryDatabase.Callback roomCallback = new RoomDatabase.Callback() {
#Override
public void onCreate(#NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
new PopulateDbAsyncTask(INSTANCE).execute();
}
};
private static class PopulateDbAsyncTask extends AsyncTask<Void, Void, Void> {
private RecoveryDao recoveryDao;
private PopulateDbAsyncTask(RecoveryDatabase db) {
recoveryDao = db.recoveryDao();
}
#Override
protected Void doInBackground(Void... voids) {
// First input is the day and the second is the num of likes for that day
recoveryDao.insert(new Recovery(6,1));
recoveryDao.insert(new Recovery(7,2));
recoveryDao.insert(new Recovery(8,3));
return null;
}
}
}
In my Dao class I currently have Insert, Update, deleteAll, and getAll... Methods.
Here is the Dao:
#Dao
public interface RecoveryDao {
#Insert
void insert(Recovery recovery);
#Update
void update(Recovery recovery);
#Query("DELETE FROM recovery_table")
void deleteAllRecovery();
// Sends data from ascending day to the call. (1,2,3,4 ....)
#Query("SELECT * FROM RECOVERY_TABLE ORDER BY day ASC")
LiveData<List<Recovery>> getAllRecovery();
}
Now, I want to retrieve the data from the Room database based on the day. So I want the num of likes for day 6, which would be 1. I want to retrieve the data and store it into an int variable in mainActivity.
So my end goal is the have many rows of data in the database and retrieve that and store that into an ArrayList, but I must first figure out how to retrieve data first.
I have tried many solutions from stackover flow, but I have not yet figured it out. All tutorials on YT all use Recycler view and adapters, but I will not be using them.
I am very new to sqlite and MVVM. Thank you for the help!!!
Try this query you need to pass the day in argument .
#Query("SELECT * FROM RECOVERY_TABLE WHERE day=:day ORDER BY day ASC ")
LiveData<List<Recovery>> getRecoveryWithDay(int day);
this will give you the list of Recovery with the matching day , you can change return type to List<Recovery> from LiveData<List<Recovery>> if you need
Let me know if you see any error .

i keep getting increased repetitive onChange passes on my observables with database changes

I have a Dictionary app where I want to assign existing synonyms to a word in the dictionary. To accomplish this I am using is using a M:N relationship between the word and synonym tables.
Entities:
#Entity(tableName = "word_table",
indices = #Index(value = "word", unique = true))
public class Word {
#PrimaryKey(autoGenerate = true)
private long id;
private String word;
#Ignore
public Word(String word) {
this.word = word;
}
public Word(long id, String word) {
this.id = id;
this.word = word;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
}
#Entity(tableName = "synonym_table")
public class Synonym {
#PrimaryKey(autoGenerate = true)
private long sid;
private String synonym;
#Ignore
public Synonym(String synonym) {
this.synonym = synonym;
}
public Synonym(long sid, String synonym) {
this.sid = sid;
this.synonym = synonym;
}
public long getSid() {
return sid;
}
public void setSid(long id) {
this.sid = sid;
}
public String getSynonym() {
return synonym;
}
public void setSynonym(String synonym) {
this.synonym = synonym;
}
}
#Entity(tableName = "word_synonym_join_table",
primaryKeys= {"word_id" , "synonym_id"},
foreignKeys = {#ForeignKey(entity = Word.class, parentColumns = "id", childColumns = "word_id"),
#ForeignKey(entity = Synonym.class, parentColumns = "sid", childColumns = "synonym_id")})
public class WordSynonymJoin {
#ColumnInfo(name = "word_id")
private long wordId;
#ColumnInfo(name = "synonym_id")
private long synonymId;
public WordSynonymJoin(long wordId, long synonymId) {
this.wordId = wordId;
this.synonymId = synonymId;
}
public long getWordId() {
return wordId;
}
public void setWordId(long wordId) {
this.wordId = wordId;
}
public long getSynonymId() {
return synonymId;
}
public void setSynonymId(long synonymId) {
this.synonymId = synonymId;
}
}
To retrieve the data for the Word and associated Synonyms, I created a POJO called WordWithSynonyms.
public class WordWithSynonyms {
#Embedded
public Word word;
#Embedded
public WordSynonymJoin wordSynonymJoin;
}
The Daos are as follows:
#Dao
public interface WordDao {
#Query("SELECT * FROM word_table")
public LiveData<List<Word>> getAllWords();
#Query("SELECT * FROM word_table WHERE id =:wordId")
public LiveData<List<Word>> getWordById(long wordId);
#Query("SELECT * from word_table WHERE word =:value")
public LiveData<List<Word>> getWordByValue(String value);
#Insert
public long insert(Word word);
#Delete
public void delete(Word word);
#Update
public void update(Word word);
#Query("DELETE FROM word_table")
public void deleteAll();
}
#Dao
public interface SynonymDao {
#Query("SELECT * FROM synonym_table")
public LiveData<List<Synonym>> getAllSynonyms();
#Query("SELECT * FROM synonym_table WHERE synonym =:value")
public LiveData<List<Synonym>> getSynonymByValue(String value);
#Insert
public void insert(Synonym synonym);
#Delete
public void delete(Synonym synonym);
#Query("DELETE FROM synonym_table")
public void deleteAll();
}
#Dao
public interface WordSynonymJoinDao {
#Query("SELECT * FROM word_table INNER JOIN word_synonym_join_table " +
"ON word_table.id = word_synonym_join_table.word_id " +
"WHERE word_synonym_join_table.synonym_id =:synonymId")
public LiveData<List<WordWithSynonyms>> getWordsBySynonym(long synonymId);
#Query("SELECT * FROM synonym_table INNER JOIN word_synonym_join_table " +
"ON synonym_table.sid = word_synonym_join_table.synonym_id " +
"WHERE word_synonym_join_table.word_id =:wordId")
public LiveData<List<SynonymWithWords>> getSynonymsByWord(long wordId);
#Query("SELECT * FROM synonym_table INNER JOIN word_synonym_join_table " +
"ON synonym_table.sid = word_synonym_join_table.synonym_id " +
"WHERE word_synonym_join_table.word_id !=:wordId")
public LiveData<List<SynonymWithWords>> getSynonymsByNotWord(long wordId);
#Insert
public void insert(WordSynonymJoin wordSynonymJoin);
#Delete
public void delete(WordSynonymJoin wordSynonymJoin);
#Query("DELETE FROM word_synonym_join_table")
public void deleteAll();
}
When I arrive on the Synonyms Activity, i pass the wordId to retrieve the current synonyms for that word through a ViewModel observer.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_synonym);
Intent intent = getIntent();
wordId = Long.parseLong(intent.getStringExtra(EXTRA_WORD_ID));
//SynonymViewModel synonymViewModel = ViewModelProviders.of(this).get(SynonymViewModel.class);
WordSynonymJoinViewModel wordSynonymJoinViewModel = ViewModelProviders.of(this).get(WordSynonymJoinViewModel.class);
//synonymAdapter = new SynonymListAdapter(this);
synonymAdapter = new SynonymWithWordListAdapter(this);
synonynRecyclerView = findViewById(R.id.recycler_view_syonym);
if (wordId != 0) {
wordSynonymJoinViewModel.getSynonymsByWord(wordId).observe(SynonymActivity.this, new Observer<List<SynonymWithWords>>() {
#Override
public void onChanged(#Nullable List<SynonymWithWords> synonymWithWords) {
synonymAdapter.setSynonyms(synonymWithWords);
synonymAdapter.notifyDataSetChanged();
}
});
}
synonynRecyclerView.setAdapter(synonymAdapter);
synonynRecyclerView.setLayoutManager(new LinearLayoutManager(SynonymActivity.this));
}
I then give the user the opportunity to associate an existing, unassigned synonym from the Synonym table to the Word table.
I retrieve the unused and available Synonyms through a separate ViewModel observer inside of an AlertDialog which uses a spinner to display them via the WordSynonymJoin table using another ViewModel observer.
Finally, inside of that ViewModel observer when the user clicks the OK button on the AlertDialog, a third VieModel observer is ran to do the actual insertion into the WordSynonymJoin table.
case R.id.synonym_assign_synonym:
final WordSynonymJoinViewModel wordSynonymJoinViewModel = ViewModelProviders.of(SynonymActivity.this).get(WordSynonymJoinViewModel.class);
wordSynonymJoinViewModel.getSynonymsByNotWord(wordId).observe(SynonymActivity.this, new Observer<List<SynonymWithWords>>() {
#Override
public void onChanged(#Nullable List<SynonymWithWords> synonymWithWords) {
List<String> synonymsNotAssignList = new ArrayList<>();
for (SynonymWithWords sww : synonymWithWords)
synonymsNotAssignList.add(sww.synonym.getSynonym());
AlertDialog.Builder assignSynonymDialog = new AlertDialog.Builder(SynonymActivity.this);
assignSynonymDialog.setTitle("Select New Category:");
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.alert_dialog_spinner_view, null);
final Spinner synonymSpinner = (Spinner) view.findViewById(R.id.alert_dialog_spinner);
final SynonymViewModel synonymViewModel = ViewModelProviders.of(SynonymActivity.this).get(SynonymViewModel.class);
ArrayAdapter<String> spinnerAdapter = new ArrayAdapter(SynonymActivity.this, android.R.layout.simple_spinner_dropdown_item, synonymsNotAssignList);
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
synonymSpinner.setAdapter(spinnerAdapter);
synonymSpinner.setSelection(synonymId);
assignSynonymDialog.setView(view);
assignSynonymDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
final String synonymValue = synonymSpinner.getSelectedItem().toString();
// get new synonym id
synonymViewModel.getSynonymByValue(synonymValue).observe(SynonymActivity.this, new Observer<List<Synonym>>() {
#Override
public void onChanged(#Nullable List<Synonym> synonyms) {
long id = 0;
if (!synonyms.get(0).getSynonym().equals(synonymValue)) {
if (synonyms.size() > 1)
Toast.makeText(SynonymActivity.this, "Query found " + synonyms.size() + " which is more than the one expected.", Toast.LENGTH_SHORT).show();
} else {
id = synonyms.get(0).getSid();
}
WordSynonymJoinViewModel wordSynonymJoinViewModel = ViewModelProviders.of(SynonymActivity.this).get(WordSynonymJoinViewModel.class);
wordSynonymJoinViewModel.insert(new WordSynonymJoin(wordId, id));
}
});
}
});
assignSynonymDialog.setNegativeButton("Cancel", null);
assignSynonymDialog.create();
assignSynonymDialog.show();
}
});
return true;
On the first pass, all seems to work well. However, on successive passes where the user continues to add new synonyms to the word, it takes that many clicks on the cancel button of the AlertDialog to exit after each synonym added. 2 synonyms added, 2 click on the cancel to get back to main Activity. 3 synonyms added, 3 clicks on the cancel to remove the AlertDialog.
I am very new to this whole concept of MVVM and Room persistence so I know there will be issues. Here is the code for the AlertDialog for adding existing, unassigned synonyms to the current word.
I don't like how much code is being used for this, but i have not been able to word my searches so that I can find ways around it.
My questions are:
Why is the code cycling +1 every time I enter associate new synonym to the word? Am I suppose to be clearing something out.
Is this coding even remotely right?
This seems like an awful lot of work to accomplish something so seemingly small. I think I have missed something. Have I made this abnormally complicated?
What am I missing that this code looks so cumbersome and unwieldy?
It seems a very cumbersome way to retrieve values and I don't really think i need to observe every query that I ran above. Maybe I am wrong.
Is there a direction of study that will help me understand this better?
Could this be where the Rx Java comes in?
I can certainly provide more code as needed.
Any help would be appreciated.
TRDL: Don't call .observe outside of ON_CREATE state.
You made a LiveData mistake... but you are not alone! That mistake is the most common LiveData mistake on StackOverflow: calling .observe outside of Activity#onCreate(). This includes calling .observe in a click listener, on onResume, broadcast receiver, etc.
The problem I see in most people who uses LivedData for the first time is that they treat LiveData just like a call back, when they are not. LiveData is a stream. LiveData does not notify just one time. The Observers attached to the LiveData will continue to be notified until they are unsubscribed. Also, It is meant to be subscribed at the beginning of the life-cycle, (e.g. Activity#onCreate or Fragment#onViewCreated) and unsubscribed at the end of the life-cycle. LiveData automatically handles the unsubscription part, so all you need to make sure is to subscribe in onCreate.
The fundamental reason you are keep getting +1 Dialog is that the previous observer is not dead and you are keep adding a new subscription to the database each time you repeat the same thing. Try rotating the phone and see if the number of dialog resets back to 1. That's because all of the previous observers are unsubscribed when you rotate the screen and activity is recreated.
Maybe you could call isShowing() and see if any dialog is open, as suggested in another answer. However, doing so is just a work around. What if it was a Toast or something else that you can't check? Besides, you are lucky that you could easily spot this bug. You might be having this duplicate observer bug some place else that is not visually noticeable.
So I think you already know how to use LiveData, but it is just that you need to know how to implement reactive pattern correctly. It would be too much to explain in one writing but let me give you a simple example:
Lets say you have a button that when you press, you fetch some data from DB. In a callback-like design you often call some function in ViewModel and pass a callback instance. For example you have this:
//ViewModel
void getSynonymsByNotWord(WordSynonymJoin word, Callback callback) { ... }
//Activity
void onClick(View v) {
wordSynonymJoinViewModel.changeCurrentSysnonymsByNotWord(wordId, callback);
}
You perform an action to ViewModel and you receive the response through callback. This is perfectly fine for callback. However, you can't do the same with LiveData. When using LiveData, View layer don't expect that there will be a response for each of the action. Instead, View layer should always blindly listen to the response, even before the button is clicked.
//ViewModel
private MutableLiveData wordQuery;
private Livedata synonymsByNotWord = Transformations.switchMap(wordQuery, word -> {
return repository.getSynonymsByWord(word);
});
LiveData getCurrentSynonymsByNotWord() {
return synonymsByNotWord;
}
void changeCurrentSynonymsByNotWord(WordSynonymJoin word) {
wordQuery.postValue(word);
}
//Activity
void onCreate() {
wordSynonymJoinViewModel.getCurrentSynonymsByNotWord().observe(...);
}
void onClick(View v) {
wordSynonymJoinViewModel.changeCurrentSynonymsByNotWord(wordId);
}
And also it is okay to, but you normally don't get ViewModel from ViewModelProviders every time you need a view model. You should just get one view model at onCreate, save it as an activity instance variable, and use the same instance in the rest of the activity.
Here:
wordSynonymJoinViewModel.getSynonymsByNotWord(wordId).observe(SynonymActivity.this, new Observer<List<SynonymWithWords>>() {
you are monitoring for synonyms, but inside of the observing, you show a dialog and allow more synonyms to be added. Everytime a new synonym is added, it creates a new AlertDialog.
So this is why you have to press cancel on each dialog.
To fix that, you can assign your AlertDialog to a field and use the isShowing() method to decide if you want to show another dialog (i.e. don't show another one if one is already showing.
https://developer.android.com/reference/android/app/Dialog.html#isShowing()
As for all your other questions, I'm sorry it's a bit too much for me to unpack.
I can share my thoughts on how I would do this though:
I want to assign existing synonyms to a word in the dictionary.
Perhaps forget the database to start with and create an in memory solution.
Then later you can change this to be persisted.
In memory the structure looks like a Hashtable of Dictionary words and Synonym lookups Map<String, List<String>>.
This Map would be in a class called Repository that exposes someway for you to observe and update it (RxJava Observable) or LiveData like you have already.
Your Fragment would observe this Map displaying it in a RecyclerView using MVVM or MVP whatever you want.
You have a clicklistener on each row of the RecyclerView to add a new synonym. On click opens the dialog (or a new activity/fragment). After the user types the synonym you will save this through the repository to your Map - and therefore the original observer will update the RecyclerView.
You should not get in a loop state of opening multiple dialogs :/
Hope that helps, tbh it sounds like you are on the right track and just need to work at it a bit more.

Accessing data from ROOM DB using ViewModel and ID

Suppose I have got a list of data in the Room DB.
Let the data be: setId, formId, formName.
There can be multiple formId in the single setId. Let setId 1 contains 10 forms, 2 contains 5 forms.
Now what I wanna do is, extract the data from the db using the setId in the ViewModel.
Let my dao be:
#Query("SELECT * FROM form WHERE setId = :id")
LiveData<List<Form>> getAllFilledForms(int id);
How can I implement such action in ViewModel.
I want to retrieve all the list of the forms where the set id is same, let 1.
Edit:
ViewModel Class:
public class ListSetViewModel extends AndroidViewModel {
private final LiveData<List<FormSet>> allFormSets;
private FormDatabase formDatabase;
public ListSetViewModel(#NonNull Application application) {
super(application);
formDatabase = FormDatabase.getDatabase(application);
allFormSets = formDatabase.formSetDao().getAllFilledForms(setId);
}
public LiveData<List<FormSet>> getAllFormSets(setId){
return allFormSets;
}
}
You need to inject your ViewModel with an ID by a Factory or Dagger2. Or you can use a public method to get data.
public LiveData<List<FormSet>> getAllFormSets(setId){
return allFormSets = formDatabase.formSetDao().getAllFilledForms(setId);
}

Room database - Access data from second activity

I apologize if this is a duplicate.
I'm currently working on a ToDo app and I'm using the Room database library to display a list of items using a RecyclerView. From the main activity, I am able to access the information from the database using the adapter. No problem here.
The thing is that when I press on one of the items, I want to open a DetailActivity where the user can modify the ToDo. Currently I'm getting the desired information using putExtra and hasExtra:
MainActivity
private void initializeAdapterForRecyclerView(){
mAdapter = new ToDoAdapter(new ToDoAdapter.ToDoClickListener() {
#Override
public void onToDoClick(int clickedItemIndex) {
Intent intent = new Intent(ToDoActivity.this, EditorActivity.class);
Log.d(LOG_TAG, "This is " + mAdapter.getToDoPosition(clickedItemIndex).getTitle());
intent.putExtra(Intent.EXTRA_TEXT, String.valueOf(clickedItemIndex));
intent.putExtra("existingTitle", mAdapter.getToDoPosition(clickedItemIndex).getTitle());
intent.putExtra("modifiedTitle", mAdapter.getToDoPosition(clickedItemIndex).getDisplayTitle());
intent.putExtra("existingDescription", mAdapter.getToDoPosition(clickedItemIndex).getDescription());
startActivity(intent);
}
});
mToDoList.setAdapter(mAdapter);
}
DetailActivity
private void getExistingToDoContent() {
Intent intent = getIntent();
if (intent.hasExtra("existingTitle")) {
String displayTitle = intent.getStringExtra("modifiedTitle");
Log.d(LOG_TAG, "Getting the title: " + displayTitle);
mTitleEditText.setText(displayTitle);
String existingDescription = intent.getStringExtra("existingDescription");
Log.d(LOG_TAG, "Getting the description: " + existingDescription);
mDescriptionEditText.setText(existingDescription);
}
}
The issue comes when I want to delete the item from the DetailActivity as I want to do this with the the ViewModel class.
ToDoViewModel
public void delete(ToDo toDo){
mRepository.delete(toDo);
}
ToDoRepository
public void delete(ToDo todo){
new deleteAsyncTask(mToDoDao).execute(todo);
}
private static class deleteAsyncTask extends AsyncTask<ToDo, Void, Void> {
private ToDoDao mAsyncToDoDao;
deleteAsyncTask(ToDoDao dao){
mAsyncToDoDao = dao;
}
#Override
protected Void doInBackground(ToDo... toDos) {
mAsyncToDoDao.deleteToDo(toDos[0]);
return null;
}
}
}
So my question is, is it possible to access the database entry of the clicked item from the DetailActivity to populate the fields and delete / update the entry using the methods from the ViewModel activity? (other than using putExtra / hasExtra)
Thank you

greenDao get auto-increment-ed ID

Is it any way for me to get the next available ID for a table row (that would be automatically created when inserting a row in the table), so I would not be forced to insert that row at a given time, to get it?
To be more precise: I have an activity which contains a listview and each of those items are added using a second activity. When I finish adding the item details in the second activity, I pass that item through a parcelable object (I implemented Parcelable Interface to one of the holders class that DaoGenerator created). The id value of that object can not be null, to pass it with writeLong(id), and receive it with readLong() in my Parcelable methods, so I have to auto-generate the id value, by inserting the current item already in the database.
What I would like to do is: generate those IDs (without inserting the item in the database), pass that item to first activity, and when user decides to save all those items from the list, I would add all of them to database in a single transaction.
some sample code I have atm:
public class Question implements Parcelable {
private Long id;
private String questionContent;
// KEEP FIELDS - put your custom fields here
// KEEP FIELDS END
public Question() {
}
public Question(Long id) {
this.id = id;
}
public Question(Long id,String questionContent) {
this.id = id;
this.questionContent = questionContent;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
// KEEP METHODS - put your custom methods here
// begin Parcelable implementation
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(id);
dest.writeString(questionContent);
}
public static final Parcelable.Creator<Question> CREATOR = new Parcelable.Creator<Question>() {
public Question createFromParcel(Parcel in) {
return new Question(in);
}
public Question[] newArray(int size) {
return new Question[size];
}
};
private Question(Parcel in) {
id = in.readLong();
questionContent = in.readString();
}
// end Parcelable implementation
// KEEP METHODS END
}
and this is how I create and send the item to list:
Question questionHolder = new Question(
null, etItemContent.getText().toString() .trim(),);
Log.d(LOG_TAG, "question id = "
+ questionHolder.getId());
// inserting it here, would auto-generate the ID I required,
// but I would like to do that to all of the items in the first Activity (containing the list of all of the items)
// questionDao.insert(questionHolder);
Log.d(LOG_TAG, "question id = "
+ questionHolder.getId());
// add item to intent
Bundle b = new Bundle();
b.putParcelable(IMPORTANCE_TAG, questionHolder);
Intent intent = new Intent();
intent.putExtras(b);
setResult(RESULT_OK, intent);
QuestionItemActivity.this.finish();
I would not suggest this as it create too much tight coupling.
a couple options that comes to my mind:
If a field is nullable, I would suggest adding another flag to parcelable to denote if that field is null or not.
so when writing
if(id == null) {
out.writeByte((byte)0);
} else {
out.writeByte((byte)1);
out.writeLong(id);
}
and when reading
boolean hasId = in.readByte() == 1;
if(hasId) {
id = in.readLong();
}
Another option, since db ids start from 1, you can set id to 0 and handle this logically. so when you receive the object in your first activity, you can check the id and set to null if it is 0.
Yes there's a mean to do that, if you're using an ORM, this would be easy as !##%.
All you have to do for example is:
Get the sequence name that generates the ID (there's always one even if you didn't create it manually).
Create an SQL query in your code for example :
session.createSQLQuery( "SELECT nextval( 'mySequenceName' )");
Then execute the query to retrieve the unique ID.
I hope this will help.
Cheers

Categories

Resources