What's the best way to update LiveData in Android? - android

I have the two ways to update a LiveData's value.
Fitst
myLiveData.value = myLiveData.value?.apply {
arg1 = value1
arg2 = value2
}
Just update existing value and pass it again.
Second
viewState.value = MyObject(arg1 = value1, arg2 = value2)
Create a new object every time and pass it.
Whisch the way is better in terms of optimisation and code beauty?
P.S. The first term is much more important. Thx in advance.

If you have two values that must be available at the same time, the second approach is the only one that makes sense. With the first approach, the first value will get quickly overwritten by the second. It's entirely possible that an observer could miss the first value. And, an observer that gets attached after the second value is set will only ever see the second value.
The cost of creating a new object every time is not very big. Don't try to optimize that way - it's simply not relevant.

Related

KOTLIN Why when i changed a List it is also accidentally changing another list

Hello i want to know why is my program changing selectedDataEdited List when i only changing editTransactionList ?
var editTransactionList: MutableList<Transaction>? = mutableListOf()
var selectedDataEdited: List<Transaction>? = listOf()
editTransactionList = listTest as MutableList<Transaction>
selectedDataEdited = listTest
var position = 0
println("edit $editTransactionList")
println("select $selectedDataEdited")
editTransactionList.get(position).apply {
amount = 2000
name = "K"
}
println("edit $editTransactionList")
println("select $selectedDataEdited")
editTransactionList.get(position).apply {
amount = 3000
name = "Z"
}
println("edit $editTransactionList")
println("select $selectedDataEdited")
the output is
edit [Transaction(amount=1000, name=T, test=1)]
select [Transaction(amount=1000, name=T, test=1)]
edit [Transaction(amount=2000, name=K, test=1)]
select [Transaction(amount=2000, name=K, test=1)]
edit [Transaction(amount=3000, name=Z, test=1)]
select [Transaction(amount=3000, name=Z, test=1)]
Variables are basically references. When you store an object in a variable you actually say "when using this variable please refer to this object". So if you "store" the same object into 2 different variables, each of them still refers to that same object. Getting the object using the first variable, making changes to it, and then accessing the second variable, will still get you that changed object.
You will need to copy the list to prevent the unwanted behavior. Keep in mind though that you would probably need a deep copy. Simply calling toList() on it for example only makes a shallow copy, which means that even though it will be a different list, the objects inside it will still refer to the original.
It's hard to tell what would work without knowing what Transaction looks like. If Transaction is a data class then selectedDataEdited = listTest.map { it.copy() } might work. See this example https://pl.kotl.in/Q_o8pYXVs
KOTLIN Why when i changed a List it is also accidentally changing another list
Because you don't have "another" list. You only have one list.
When you do selectedDataEdited = listTest, you assign a second reference to the same list. If you want two separate lists, you must create them, possibly by cloning the original list.
Instead of using as MutableList use toMutableList:
editTransactionList = listTest.toMutableList()
It will make a copy of your list instead of passing a reference to the same list.

is it reliable, if i used to check in a list using any before going with foreach in the below example?

Just wondering to check is there any object has isSelected value as true, if so then do a foreach to add the particular object in another list. Is this good way to prevent the foreach or still directly do foreach without any. Because inside the any i can see they do the same foreach. Experts please advice.
final isAnyMainGod = listMainGod.any((element) => element.isSelected);
if (isAnyMainGod) {
listMainGod.forEach((element) {
if (element.isSelected) {
_tempID.add(
FilterData(type: 'MAINGOD', filterValue: element.mainGodNameId));
}
});
}
The issue I see here is that you are doing a potential full iteration of the list, followed up by another full iteration of the list, applying identical logic a second time.
You could do something like this:
var _tempId = listMainGod.where((element) => element.isSelected)
.map((e) => FilterData(type: 'MAINGOD', filterValue: e.mainGodNameId))
.toList();
In the my suggestion, the condition in the where will remove any elements from the list, that don't evaluate to a true. There is still a full iteration of the list (but you'll have to do that anyway at some point), but this suggestion only has 1 full iteration, and a single line of code for the condition (as opposed to your two occurrences of element.isSelected).
Then, the map, is an iteration on only the matching list items, to apply give to the FilterData function.
In the event that no matching elements are found, you are provided a list with 0 elements.
The other added benefit of writing something like this, is it requires less cognitive load, to follow. You don't to know or care if isAnyMainGod exists (or if you have to look and see if it's used elsewhere, because that one spot), you just iterate over any results you have from the result. In my experience, the fewer variables you use to track state results fewer potential places you can introduce bugs.

How do i make a history calculator in android?

I am making a calculator same as windows calculator. I am stuck at the history feature. which would be the best UI control to implement the history feature as seen in Windows Calculator?
I also want onclick events on the history.
I'm not sure how you represent a calculation, but you could have a simple class like this:
enum Operator {PLUS,MINUS,DIV,MULT};
class Calculation {
float operand1,operand2;
Operator operator;
public Calculation(float op1,float op2,Operator operator){
this.operand1=op1;
this.operand1=op2;
this.operator=operator;
}
}
Then when a calculation is done, create an object of this type and add it to an ArrayList:
List<Calculation> history = new ArrayList<Calculation>();// history
history.add(new Calculation(5,5,Operator.PLUS));// add a new `Calculation` to our list
Then access the list with history.get(some_integer), based on your UI.
Could you just use a List containing a number of previously entered calculations? If you knew the maximum possible history size in advance, you could just stick with a normal array, but a List will give you more flexibility.
You need to store all the operations and results with an index here. Increase the index every time when you perform an operation.To retrieve the past operation, manipulate the index and you can get the values.You can use Collection API for storing the operations.

For loop not terminating - Android

I don't know why but my for loop won't 'stop' when its reached the truth of the termination statement.
for(int i = 1; i < 11; i++){
edittext.setText("");
EasyGame();
//if(i==10){
//Game.this.finish();
//}
}
EasyGame() is an arithmetic method, just adds two numbers together. I tried using the if statement shown above, but it still wouldn't do anything, and if it did it would call finish() after the first question!
If someone would be kind to help me I would be grateful.
EDIT:
public void EasyGame(){
Random rand = new Random();
final int a = (int) rand.nextInt(20)+1;
final int b = (int) rand.nextInt(20)+1;
String aString = Integer.toString(a);
String bString = Integer.toString(b);
String display = aString + " + " + bString + " =";
questionLabel.setText(display);
c = a + b;
}
that for loop is inside a switch/case, which deals with onClick() for buttons
Very difficult to say without seeing more code, but what you have posted alone is inherently flawed because you're trying to continuously update a UI element within a loop. If that loop is running on the UI thread, then the system isn't going to be able to redraw any UI elements such as your edittext until the loop (and whatever containing callback method) exits.
Therefore, when you say "I tried using the if statement shown above, but it still wouldn't do anything, and if it did it would call finish() after the first question!" I make the assumption that you're believing that the loop is only iterating once because you only ever see edittext display whatever is passed in the last ever .setText() call.
I dont see anything wrong with that code. The only possible problem is that your counter is being decremented somewhere (for example inside EasyGame();), or the problem is somewhere else
In the lack of provided code, I assume that your indefinite loop is happening inside EasyGame() method
The loop probably only runs once, and then it gets halted by a never ending loop in EasyGame().
Note: Don't use initial capitalized letters for methods, it's confusing.
I agree with Trevor Page, and i'll try and clarify :
your code, if it runs on a callback on the UI thread, could be calling itself by generating a callback when you are clearing the first textView or modifying the second.
Also, what do you mean by 'it won't stop' ? I don't quite see what you are trying to do here, since you erase 10 times the content of a textView and replace 10 times the content of another one.

how to increment a variable in first activity depending on the TextView values in second activity

hi all I have a variable in first activity i need to add values returned from second activity and store it in this variables. Switching between activities happens multiple times.... Any ideas..?
here is a piece of code which stores current value each time and not the Sum of it...
double quantity = Double.parseDouble(s1[1]);
double amount = Double.parseDouble(s1[2]);
if(s1[3].equals(""))
{
totalint = (quantity*(amount));
Log.d("hitherebbbbbbb",((Double)totalint).toString());
grandTotal =+totalint;
}
else
{
deduction = Double.parseDouble(s1[3]);
totalint = ((quantity*(amount-deduction*amount/100)));
Log.d("hitherebbbbbbb",((Double)totalint).toString());
grandTotal =+totalint;
}
If the amount of variables stays the same you could always use sharedpreferences. They are super simple to use and you can add a sharedpreference listener to update your activity when a value is changed. If the amount of variables changes (eg you have 3 integers at one time but maybe your user can change it so you need 5) then I would do something a little more complex that may not be the best option but I like it because I find it more simple than a database. Let me know which scenario best describes your situation and I'll get you more documentation.
You probably want to return the values from the second activity through its return intent and do a startActivityForResult() in the first activity.
you would do this by creating an intent in your second activity, setting any relevant return data, and calling
setResult(Activity.RESULT_OK, returnIntent);
finish();
You will be called back in the onActivityResult() method when the second activity is finished. You would then extract the values from the return intent and update your local storage.

Categories

Resources