Reputation: 674
I am building an app that allows the user to store usernames & passwords. The user clicks on the FAB and the AddEditEntry.java
activity starts. The user enters a username, enters or generates a password, enters a hint and clicks save. The new data is presented on a list in the Mainactivity.java
. If the user chooses to edit the entry, all s/he needs to do is to long click the item and the same AddEditEntry.java
class starts with the previous data in the fields. The user is then able to change that data and hit save to update the entry. There is also a button on the action bar to delete all entries or the user can swipe the entry left/right to remove it off of the database.
Instead, here is what happens:
AddEditEntry.java
successfully inflates the fields with previous dataThe app is built with the MVVM architecture so I have (entity, DAO, database, repository, viewmodel) classes, as well as the necessary adapter class. I will post only the relevant code to avoid cluttering as much as possible. I can add more code per request.
MainActivity.java:
@Override
protected void onCreate(Bundle savedInstanceState) {
...
//Sends the existing entry for editing
adapter.setOnItemLongClickListener(new RecyclerViewAdapter.OnItemLongClickListener() {
@Override
public void onItemLongClick(Entries entries) {
Intent intent = new Intent(MainActivity.this, AddEditEntry.class);
intent.putExtra(AddEditEntry.EXTRA_USERNAME, entries.getUsername());
intent.putExtra(AddEditEntry.EXTRA_HINT, entries.getHint());
intent.putExtra(AddEditEntry.EXTRA_PASSWORD, entries.getPassword());
intent.putExtra(AddEditEntry.EXTRA_ID, entries.getId());
startActivityForResult(intent, EDIT_ENTRY_REQUEST);
Toast.makeText(MainActivity.this, entries.getUsername(), Toast.LENGTH_SHORT).show();
Toast.makeText(MainActivity.this, entries.getHint(), Toast.LENGTH_SHORT).show();
Toast.makeText(MainActivity.this, entries.getPassword(), Toast.LENGTH_SHORT).show();
Toast.makeText(MainActivity.this, String.valueOf(entries.getId()), Toast.LENGTH_SHORT).show();
}
});
}
...
//The onActivityResult retrieves the result when the user adds
// or edits an entry by checking for the specific request code
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == ADD_ENTRY_REQUEST && resultCode == RESULT_OK){
String username = Objects.requireNonNull(data).getStringExtra(AddEditEntry.EXTRA_USERNAME);
String password = Objects.requireNonNull(data).getStringExtra(AddEditEntry.EXTRA_PASSWORD);
String hint = Objects.requireNonNull(data).getStringExtra(AddEditEntry.EXTRA_HINT);
Entries entry = new Entries(username, hint, password);
viewModel.insert(entry);
Toast.makeText(this, "Entry added!", Toast.LENGTH_SHORT).show();
}else if(requestCode == EDIT_ENTRY_REQUEST && resultCode == RESULT_OK){
int id = getIntent().getIntExtra(AddEditEntry.EXTRA_ID, -1);
String username = Objects.requireNonNull(data).getStringExtra(AddEditEntry.EXTRA_USERNAME);
String password = Objects.requireNonNull(data).getStringExtra(AddEditEntry.EXTRA_PASSWORD);
String hint = Objects.requireNonNull(data).getStringExtra(AddEditEntry.EXTRA_HINT);
if (id == -1){Toast.makeText(this, "Something went wrong", Toast.LENGTH_SHORT).show();}
Entries entry = new Entries(username, hint, password);
entry.setId(id);
viewModel.update(entry);
Toast.makeText(this, String.valueOf(id), Toast.LENGTH_SHORT).show();
Toast.makeText(this, username, Toast.LENGTH_SHORT).show();
Toast.makeText(this, password, Toast.LENGTH_SHORT).show();
Toast.makeText(this, hint, Toast.LENGTH_SHORT).show();
Toast.makeText(this, "Entry updated", Toast.LENGTH_SHORT).show();
}else{Toast.makeText(this, "Entry not added!", Toast.LENGTH_SHORT).show();}
}
AddEditEntry.java
public class AddEditEntry extends AppCompatActivity {
public static final String EXTRA_USERNAME = "com.ozbek.cryptpass.EXTRA_USERNAME";
public static final String EXTRA_HINT = "com.ozbek.cryptpass.EXTRA_HINT";
public static final String EXTRA_PASSWORD = "com.ozbek.cryptpass.EXTRA_PASSWORD";
public static final String EXTRA_ID = "com.ozbek.cryptpass.EXTRA_ID";
public static final int EDIT_ENTRY_REQUEST = 3;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
...
final Intent intent = getIntent();
// If the ID was passed, gets the extras for editing
if(intent.hasExtra(EXTRA_ID)){
setTitle("Edit Entry");
saveEntry.setText("Update Entry");
usernameEditText.setText(getIntent().getStringExtra(EXTRA_USERNAME));
passwordEditText.setText(getIntent().getStringExtra(EXTRA_PASSWORD));
hintEditText.setText(getIntent().getStringExtra(EXTRA_HINT));
int id = getIntent().getIntExtra(EXTRA_ID, -1);
Toast.makeText(this, "Info Received!!!", Toast.LENGTH_SHORT).show();
Toast.makeText(this, getIntent().getStringExtra(EXTRA_USERNAME), Toast.LENGTH_SHORT).show();
Toast.makeText(this, getIntent().getStringExtra(EXTRA_PASSWORD), Toast.LENGTH_SHORT).show();
Toast.makeText(this, getIntent().getStringExtra(EXTRA_HINT), Toast.LENGTH_SHORT).show();
Toast.makeText(this, String.valueOf(id), Toast.LENGTH_SHORT).show();
}
else{setTitle("Add Entry");}
generatePassword.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {passwordEditText.setText(generatedPassword());}});
saveEntry.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent data = new Intent();
data.putExtra(EXTRA_USERNAME, usernameEditText.getText().toString());
data.putExtra(EXTRA_HINT, hintEditText.getText().toString());
data.putExtra(EXTRA_PASSWORD, passwordEditText.getText().toString());
setResult(RESULT_OK, data);
finish();
}
});
}
...
}
EntryViewModel.java
public class EntryViewModel extends AndroidViewModel {
private EntryRepository repository;
private LiveData<List<Entries>> allEntries;
public EntryViewModel(@NonNull Application application) {
super(application);
repository = new EntryRepository(application);
allEntries = repository.getAllEntries();
}
public void insert(Entries entries){repository.insert(entries);}
public void update(Entries entries){repository.update(entries);}
public void delete(Entries entries){repository.delete(entries);}
public void deleteAll(){repository.deleteAllEntries();}
public LiveData<List<Entries>> getAllEntries() {return allEntries;}
}
Entries.java
@Entity(tableName = "entries_table")
public class Entries {
@PrimaryKey(autoGenerate = true)
private int id;
private String username, hint, password;
public Entries(String username, String hint, String password){
this.username = username;
this.hint = hint;
this.password = password;
}
public Entries(){}
public int getId() {return id;}
public void setId(int id) {this.id = id;}
public String getUsername() {return username;}
public void setUsername(String username) {this.username = username;}
public String getHint() {return hint;}
public void setHint(String hint) {this.hint = hint;}
public String getPassword() {return password;}
public void setPassword(String password) {this.password = password;}
}
Here is the full source code
Upvotes: 1
Views: 83
Reputation: 3163
Just add these fixes.
In the onClick()
of your saveEntry
(I assume its a button) in AddEditEntry.java
, change it to this:
saveEntry.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent data = new Intent();
data.putExtra(EXTRA_USERNAME, usernameEditText.getText().toString());
data.putExtra(EXTRA_HINT, hintEditText.getText().toString());
data.putExtra(EXTRA_PASSWORD, passwordEditText.getText().toString());
//You were missing these 2 lines
int id = getIntent().getIntExtra(EXTRA_ID, -1);
if(id != -1){data.putExtra(EXTRA_ID, id);}
setResult(RESULT_OK, data);
finish();
}
});
And in the onActivityResult
method inside your MainActivity.java
, do this quick fix:
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == ADD_ENTRY_REQUEST && resultCode == RESULT_OK){
...
}else if(requestCode == EDIT_ENTRY_REQUEST && resultCode == RESULT_OK){
int id = Objects.requireNonNull(data).getIntExtra(AddEditEntry.EXTRA_ID, -1);
if (id == -1){
Toast.makeText(this, "Something went wrong", Toast.LENGTH_SHORT).show();
return;
}
...
}else{Toast.makeText(this, "Entry not added!", Toast.LENGTH_SHORT).show();}
}
It should work after these. Let me know if you got any issues.
Upvotes: 1
Reputation: 666
When the user deletes an entry (whether through swiping left/right or hitting the delete all button), the new entry does not start from the ID value of 1 onwards. The entry start from where the previous entry left off. So if I delete an entry with the ID = 1, the new entry's ID = 2.
This is the default behaviour of an auto generated primary key. What is wrong with it?
Even worse, when I hit the save button to update an entry, the ID becomes -1. And when this happens, the values for the entry do not exist at all because I'm checking them with Toast messages in each state. So there is no updating and the entry remains the same.
I did not read all of the code but this looks like a conflict issue. Try adding a replace strategy to your queries.
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(Entries entries);
@Update(onConflict = OnConflictStrategy.REPLACE)
void update(Entries entries);
Upvotes: 0