Resaving object instead of creating a new one in list - java

Solved - Answer is at end of thread
I'm creating a notes app. And in that app everything is going well so far except that when I'm trying to edit the note (in a recycler view) and I click save, it creates a new one instead of resaving the contents of the existing note. Because I don't have a way to save it again, that being because I'm not sure how to go about it. Here is how I handle saving the note in my activity, CreateNoteActivity.java
// FAB
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Check to see if at least one field is populated with data
String title = etTitle.getText().toString();
String description = etDescription.getText().toString();
title = title.trim(); // Remove whitespaces at the beginning/end
description = description.trim();
// Get intent extras
Intent intent = getIntent();
String alreadyCreatedTitle = intent.getStringExtra(CreateNoteActivity.EXTRA_TITLE);
String alreadyCreatedDescription = intent.getStringExtra(CreateNoteActivity.EXTRA_DESCRIPTION);
// Check to see if note title is empty, if it is, don't save
if (title == "" || title.isEmpty()) {
Snackbar snackbar = Snackbar.make(view, "Title may not be empty", Snackbar.LENGTH_SHORT);
snackbar.show();
// If the user clicked an already made note and did not change its contents, go back to MainActivity
} else if (title.equals(alreadyCreatedTitle) && description.equals(alreadyCreatedDescription)) {
finish();
CreateNoteActivity.didClick = false;
// The user is editing a note
} else if (didClick) {
// If the title or description is different then resave the note
if (!title.equals(alreadyCreatedTitle) || !description.equals(alreadyCreatedDescription)) {
// TODO: Make it resave the note object
}
} else {
saveNote();
CreateNoteActivity.didClick = false;
}
}
});
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
After that, it comes to my MainActivity.java class where onActivityResult() handles the data and saves a new note, or updates the existing note (not yet implemented)
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 123) {
if (resultCode == Activity.RESULT_OK) {
String passedTitle = data.getStringExtra(CreateNoteActivity.EXTRA_TITLE);
String passedDescription = data.getStringExtra(CreateNoteActivity.EXTRA_DESCRIPTION);
if (CreateNoteActivity.didClick) { // User is saving an existing note
// TODO: Resave the existing note object
// **************************
} else { // User is creating a new note
notes.add(new Note(passedTitle, passedDescription));
}
}
refreshAdapter();
if (resultCode == Activity.RESULT_CANCELED) {
// Do something if it's cancelled. Happens when you click the back button for example
}
}
}
As you can see, i have a variable, "CreateNoteActivity.didClick = false;" of static boolean in this class that I am using to keep track if the user clicked on a note, and it brought them to this activity.
I keep track of that in my adapter class
#Override
public void onClick(View view) {
CreateNoteActivity.didClick = true;
Log.d("TAG", "onClick() called on row: " + getAdapterPosition());
Intent intent = new Intent(context, CreateNoteActivity.class);
intent.putExtra(CreateNoteActivity.EXTRA_TITLE, titleTV.getText().toString());
intent.putExtra(CreateNoteActivity.EXTRA_DESCRIPTION, descriptionTV.getText().toString());
((Activity) context).startActivityForResult(intent, 123);
}
So when the user clicks a note at a specific index, it passes the intent extras to CreateNoteActivity.java so it can retrieve them, and populate the edit text with their info. So now what I am wanting to do is if the user clicks save, it doesn't make a new note, but instead resaves the old note
I really would appreciate anyones help and feedback with solving this problem. Been stuck on it for a couple hours now and I just don't know how to wrap my head around going for this. Thank you very much.
My simple notes class
public class Note {
private String title;
private String description;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Note(String title, String description) {
this.title = title;
this.description = description;
}
public Note() {
// Empty
}
}
Solution
So what I ended up doing was creating a static int and setting it to getAdapterPosition() so that I could always get the position the certain object was at. I then passed it as an intent extra and retrieved it so that I could mess with it. Removed it at that specified index, and set a new one at that index.
if (CreateNoteActivity.didClick) { // User is saving an existing note
note.setTitle(passedTitle);
note.setDescription(passedDescription);
notes.remove(passedID); // Remove note so I can put that same one at the top
notes.add(0, note); // Put note at top of list
CreateNoteActivity.didClick = false;
recyclerView.scrollToPosition(0); // Scroll to top
} else { // User is creating a new note
note.setTitle(passedTitle);
note.setDescription(passedDescription);
notes.add(0, note);
recyclerView.scrollToPosition(0);
}
}

You should also store id of a Note and pass it to be able to edit. You can use its position as the id.
if (CreateNoteActivity.didClick) { // User is saving an existing note
Note anote = notes.getItem(passedNoteId);
anote.setTitle(passedTitle);
anote.setDescription(passedDescription);
} else { // User is creating a new note
notes.add(new Note(passedTitle, passedDescription));
}

Related

List listing returning object reference [duplicate]

This question already has answers here:
How do I print my Java object without getting "SomeType#2f92e0f4"?
(13 answers)
Closed 1 year ago.
I'm making an application, where I have a central recyclerview where items that the user will type are listed, below 2 buttons, one for adding items and the other for finishing. The problem I am having is that when the user finishes the task and clicks on finish I want to get all the data that was listed on his screen that is inside a List and store it in firebase, but I am not able to get this data in shape array, it always returns the object reference.
Searching the internet I found how to use the .toString in the array, but it returns me the same thing.
Here is the example of the return I am receiving.
return
the code of my object
public class ListItem {
private float measure;
public ListItem(float measure) {
this.measure = measure;
}
public float getMeasure() {
return measure;
}
public void setMeasure(float measure) {
this.measure = measure;
}
}
the code of my button add
private View.OnClickListener addItem = new View.OnClickListener() {
#Override
public void onClick(View v) {
DialogForm();
mAdapter.notifyItemInserted(listItems.size());
}
};
void DialogForm() {
AlertDialog.Builder alert = new AlertDialog.Builder(MainActivity.this);
final View customLayout = getLayoutInflater().inflate(R.layout.layout_dialog, null);
alert.setView(customLayout);
alert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
EditText measure = customLayout.findViewById(R.id.edit_measure);
String response = measure.getText().toString();
if (response.isEmpty() || response.equals("0")) {
Toast.makeText(MainActivity.this, "A medida não pode ser vazia",
Toast.LENGTH_SHORT).show();
} else {
listItems.add(new ListItem(Float.parseFloat(response)));
btnFinish.setEnabled(true);
btnFinish.setBackgroundResource(R.drawable.bg_button_enabled);
}
}
});
AlertDialog dialog = alert.create();
dialog.show();
}
the code of my button finish, when I'm listing
private View.OnClickListener finishListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
for (int i=0; i<listItems.size(); i++){
Log.d("teste", listItems.get(i).toString());
}
}
};
toString() will always return the hash of the object if not override as it is an inherited method from java.lang.Object and not specific to your object
If you want toString to return the measure variable then add the following to your ListItem class
#Override
public String toString() {
return Integer.toString(measure);
}
In order to add more entries to the method, just add another + myData but perhaps ensure there is some sort of divider to make it moire readable - such as + " || " + or something
Good luck with the project

How to change the color of an element of a recyclerview?

I want to change color of my cardview in Recyclerview if a string matches a string from QR code. I am able to display a toast if string matches, but I also want to change color of that particular element in Recyclerview.
here is the code of selecting an item for scanning
recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(getApplicationContext(), new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
tempString = passengerDataModelList.get(position).getPnr();
tempClickPosi = position;
Intent intent = new Intent("com.google.zxing.client.android.SCAN");
startActivityForResult(intent, 0);
}
}));
Now on ActivityResult I will get the result:
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == 0) {
if (resultCode == RESULT_OK) {
String contents = intent.getStringExtra("SCAN_RESULT");
String format = intent.getStringExtra("SCAN_RESULT_FORMAT");
if(contents.equalsIgnoreCase(tempString)){
Toast.makeText(this, "String MATCHED", Toast.LENGTH_SHORT).show();
///// Here I want to change the color of that item in recycler view
}else if(!contents.equalsIgnoreCase(tempString)){
Toast.makeText(this, "String NOT MATCHED", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(this, "Error in scanning", Toast.LENGTH_SHORT).show();
}
}
}
}
So please help me to change the color of that particular item from activity. If need more info kindly comment.
Thank You
For suppose you have a model
public class PassengerData{
//add this property
private boolean isMatched = false;
void setMatched(boolean matched){
this.isMatched = matched;
}
boolean isMatched(){
return isMatched;
}
}
Then in recyclerview's bindview just verify the boolean,
boolean matched = passengerDataModelList.get(position).isMatched();
cardview.setBackgroundColor(matched ? R.color.matched_color : R.color.unmatched_color);
Then in Activity
if(contents.equalsIgnoreCase(tempString)){
Toast.makeText(this, "String MATCHED", Toast.LENGTH_SHORT).show();
///// Here I want to change the color of that item in recycler view
// modify `isMatched` value for that item and call `notifyDataSetChanged`();
}
Create separate flag for color and then once string is matched update flag for particular item and then notify your adapter
According to my understanding, I guess You want to make background colorful if String is match. In RecyclerView you are inflating rows so your rows must have a Layout which You can use like below if your string is matched. The below code is only for understanding purpose. Customize it accordingly. Here I am changing color of Recycler Item, based on condition so i wrote this condition. You can modify it
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
if(position==0){
holder.itemView.setBackgroundColor(Color.BLACK);
}else{
holder.itemView.setBackgroundColor(Color.GREY);
}
holder.mTextView.setText(mDataArray.get(position));
}

Permanently save intent from other activity (with two values) to listview

I'm trying to save two values from an activity (where the user can put in two different values, one String value and one integer value) in the listview from another activity. In the first activity, it shows a list with a course and the amount of points for that course in one listview, like this:
Course: English
Points: 4
Now, the problem is, everytime I want to put in another value using the add_course_actitivty, it overwrites the previous value. I've looked at different solutions, like with sharedpreferences (Add items to listview from other activity), but this uses only one value and if I try to work with sharedpreferences, it overwrites the other value in the sharedpreferences, but I want users to add multiple courses and corresponding points. Also on restart, it deletes the values in the listview (I read to prevent this you need to store it in sharedpreferences, but this doesn't work the way I need it to be)
KeuzeActivity.class (shows the listview):
public class KeuzeActivity extends AppCompatActivity {
private FloatingActionButton fab_add;
private String student_naam;
private ListView keuze_list;
boolean wantDelete;
private ArrayAdapter adapter;
private String vak;
private int ec;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_keuze);
// setting title
student_naam = getIntent().getStringExtra("student");
setTitle("Keuzevakken en projecten van " + student_naam);
//initialzing elements
fab_add = (FloatingActionButton)findViewById(R.id.fab_add);
keuze_list = (ListView) findViewById(R.id.keuze_list);
//initializing list
final ArrayList<Course> courseItems = new ArrayList<Course>();
adapter = new ArrayAdapter<Course>(this, android.R.layout.simple_list_item_1, courseItems);
keuze_list.setAdapter(adapter);
// checks if intent has required values, put it in listview
if (getIntent().hasExtra("vak") && getIntent().hasExtra("ec")) {
vak = getIntent().getStringExtra("vak");
ec = getIntent().getIntExtra("ec", ec);
courseItems.add(new Course(vak, ec));
adapter.notifyDataSetChanged();
}
// make fab go to other activity
fab_add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(KeuzeActivity.this, add_course_activity.class));
}
});
// long press deletes item
keuze_list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
showDeleteDialog();
if (wantDelete) {
courseItems.remove(position);
adapter.notifyDataSetChanged();
}
return true;
}
});
}
private void showDeleteDialog() {
AlertDialog.Builder infobuilder = new AlertDialog.Builder(this);
infobuilder.setCancelable(false);
infobuilder.setTitle("Vak/project verwijderen");
infobuilder.setMessage("Weet je zeker dat je het vak of project wilt verwijderen?");
final TextView text = new TextView(this);
// action when pressed OK
infobuilder.setPositiveButton("Ja", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
wantDelete = true;
dialog.cancel();
}
});
infobuilder.setNegativeButton("Nee", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
wantDelete = false;
dialog.cancel();
}
});
infobuilder.show();
}
}
add_course_activity.class (let's users input course and points)
public class add_course_activity extends AppCompatActivity {
private EditText course_edit;
private EditText ec_edit;
private Button save_btn;
private String student_name;
private int ec;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_course);
setTitle("Voeg vak of project toe");
final Context context = getApplicationContext();
// initializing elements
course_edit = (EditText) findViewById(R.id.edit_vak);
ec_edit = (EditText) findViewById(R.id.edit_ec);
save_btn = (Button) findViewById(R.id.save_button);
// action on savebutton
save_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (course_edit.getText().toString().trim().length() > 0 && ec_edit.getText().toString().trim().length() > 0 ) {
ec = Integer.parseInt(ec_edit.getText().toString());
Intent goBack = new Intent(add_course_activity.this, KeuzeActivity.class);
goBack.putExtra("vak", course_edit.getText().toString());
goBack.putExtra("ec", ec);
goBack.putExtra("student", PreferenceManager.getDefaultSharedPreferences(context).getString("student_name", student_name));
startActivity(goBack);
}
else {
Toast.makeText(context, "Voer juiste informatie in!", Toast.LENGTH_SHORT).show();
}
}
});
}
}
Course.java class (getters and setters + with toString method)
public class Course {
private String vak;
private int ec;
public Course(String vak, int ec) {
this.vak = vak;
this.ec = ec;
}
public String getVak() {
return vak;
}
public void setVak(String vak) {
this.vak = vak;
}
public int getEc() {
return ec;
}
public void setEc(int ec) {
this.ec = ec;
}
#Override
public String toString() {
return ("Vak: " + vak + "\n" + "Punten: " + ec);
}
}
Note that my code isn't clean or done, but to get further I need to fix this problem.
You have several way to do it. As other replies have suggested you can use an SQLLite database and add data to a course table and retrieve data from it.
If you find Db approach to complicated/heavy
You could also use SharedPreferences what you need to do is figure a way to store a string that represent a list of course. It is not the best way to approach it but it will work.
Lets say you choose to serialize your Course object with "vac-ec"
Then you just store a serialized list of course. Example "vac1-ec1,vac2-ec2"
When you need to add a course you juste grab the previous string split it to list, append the new course to the list and re-serialize the list to a string to encode it.
Other solution could be to use Realm.
You should used SQLiteDatabase and create a table with valid attributes and insert your new values into them
Okay, now things are clearer. As answered by #Dwijraj, when storing what potentially will be a large set of data, for maximum control it is best to use SQLite.
You can read more about the different Saving Data methods here:
https://developer.android.com/training/basics/data-storage/index.html
SharedPreferences are best used to store small amounts of information, like storing the settings of an application. [Mute] for example. Or a highscore in case of a game.
A Database is a better option when it comes to storing large pieces of data that you will potentially manipulate.
Your data structure can be something like this, Courses table containing Unique_ID , Course Name, Course Level, Course summary.
A table for English for example which will contain
Exams, Scores, Duration.
There are a lot of things you can do.
Try by storing the records in SQLite, and get it when you want to show.
By this, You can have a track of all added items. And you can show the items you want.

Populating recyclerview - nothing happens

I have two recyclerviews, one to select a category, and one with various items belonging to various categories. When I click on a category in my first recyclerview, I would like to see only the items in that category displayed in the second recyclerview. In my displayDataItems method, the System.out.print gives me the correct filtered data. However, in my recyclerview, when I select a category, all items in all categories are still displayed.I'd be grateful for some pointers. Thanks in advance!
This is in my dataProvider class:
public static Predicate<DataItem> predAnimals = new Predicate<DataItem>() {
#Override
public boolean apply(DataItem dItem) {
return (dItem.getCategory() == "Animals");
}
};
public static void displayDataItems(List<DataItem> dataItemList, final Predicate<DataItem> pred) {
for (DataItem dItem : dataItemList) {
if (pred.apply(dItem)){
System.out.println(dItem);
}
}
}
And this is in my category recyclerAdapter class:
holder.myView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String itemName = item.getItemName();
Intent intent = new Intent (catContext, SelectionPage.class);
intent.putExtra(ITEM_KEY_TWO, itemName);
catContext.startActivity(intent);
switch (itemName){
case "Animals":
SampleDataProvider.displayDataItems(dataItemList, predAnimals);
Toast.makeText(catContext, "Animals", Toast.LENGTH_SHORT).show();
break;
case "Cartoons":
Toast.makeText(catContext, "Cartoons", Toast.LENGTH_SHORT).show();
break;
}
}
});
}

get/use radio button value android

I FIGURED OUT WHAT I WAS DOING. I HAD THE VARIABLE NAME IN QUOTES WITH THE REST OF THE URL STRING.
How do you save the value of a Radio button into a variable and use that variable later.
I can see the variable Day_Item in my LogCat and the value is in there but when try using Day_Item later it does not show the valuable.
Below is a section of my code that shows the buttons.
String Day_Item = null;
public class SearchDB extends Activity {
private static final String TAG = "MyApp";
String start_log = "STARTED";
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search_layout);
final RadioButton radio_monday = (RadioButton) findViewById(R.id.monday);
radio_monday.setOnClickListener(radio_listener);
cityspinner.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position,long arg3)
{
int id = parent.getId();
if (spinner2_count2 < spinner2_count1 ) {
spinner2_count2++; }
else
{
String city_spinner_log = "CITY SPINNER";
Log.d(TAG, city_spinner_log);
String item = cityspinner.getSelectedItem().toString();
String nameContentType = "name";
String cityURL = "GetRestaurant.php?day=Day_Item&city=" + item;
Log.d(TAG, cityURL);
String shop_data = DataCall.getJSON(cityURL,nameContentType);
Log.d(TAG, shop_data);
Bundle bundle = new Bundle();
bundle.putString("shopData", shop_data);
Intent myIntent = new Intent(SearchDB.this, ShowRestaurant.class);
myIntent.putExtras(bundle);
startActivityForResult(myIntent, 0);
}
}
}
//ONCLICKLISTENER that saves RADIO value into a variable.
public OnClickListener radio_listener = new OnClickListener() {
public void onClick(View v) {
// Perform action on clicks
RadioButton rb = (RadioButton) v;
Day_Item = (String) rb.getText();
Log.d(TAG,Day_Item);
Toast.makeText(SearchDB.this, Day_Item, Toast.LENGTH_SHORT).show();
}
};
}
You would need a bit more code to get a good solid answer. Such as how is Day_Item allocated? And is it's scope global? Are you calling it from another activity or the one it's allocated within? These are just guesses at this point:
1) Are you sure your onClickListener isn't firing multiple times? Thus setting Day_Item to an undesired text or nothing at all?
2) Rather a question/answer,
"but when try using Day_Item later it does not show the valuable"
I'm assuming this means that it is null? Well if it's being set properly, and then it is being null'd... it either is being explicitly null'd by you somewhere (such as (1)) or else the allocation and scope are the issue area I believe...

Categories