RxJava combineLatest - observable from changes - android

I create form with 15 inputs and I want observe those inputs to check if something was changed, I compare results of inputs with current userModel. How can I reduce that code because seems to be little bit complicated. It looks like that:
Observable.combineLatest(fieldsViewHolder.observableInputsChanges(), new FuncN<Boolean>() {
#Override
public Boolean call(Object... args) {
if(userModel != null) {
return args[0].toString().equals(userModel.getFirstName()) && args[1].toString().equals(userModel.getLastName()) && args[2].toString().equals(userModel.getEmail()) &&
args[3].toString().equals(userModel.getMobilePhone()) && args[4].toString().equals(userModel.getCompanyPlace()) && args[5].toString().equals(userModel.getCompanyName()) &&
args[6].toString().equals(userModel.getCountry()) && args[7].toString().equals(userModel.getCompanyPosition()) && args[8].toString().equals(userModel.getPhone()) &&
args[9].toString().equals(userModel.getPostalCode()) && args[10].toString().equals(userModel.getStreet1()) && args[11].toString().equals(userModel.getStreet2()) &&
args[12].toString().equals(userModel.getFirstName()) && args[13].toString().equals(userModel.getWebPage()) && args[14].toString().equals(userModel.getCity());
}
return args[0].toString().isEmpty() && args[1].toString().isEmpty() && args[2].toString().isEmpty() &&
args[3].toString().isEmpty() && args[4].toString().isEmpty() && args[5].toString().isEmpty() &&
args[6].toString().isEmpty() && args[7].toString().isEmpty() && args[8].toString().isEmpty() &&
args[9].toString().isEmpty() && args[10].toString().isEmpty() && args[11].toString().isEmpty() &&
args[12].toString().isEmpty() && args[13].toString().isEmpty() && args[14].toString().isEmpty();
}
});

you can create UserModel object with constructor (pass all args to it)
in constructor map every args to field you want. now you have another UserModel.
you can compare them by overriding equal for UserModel or you can convert them with Gson and compare String! I prefer first solution.
Update
for empty lines that you add after edit you can check like this:
for(int i = 0; i < 15; i++){
if(!args[i].toString().isEmpty()) {
return false;
}
}
return true;

Related

Android: how to avoid Method invocation... may produce 'NullPointerException' warning?

I do the following:
if (!items.containsKey(item) || items.get(item).getPrice() != 0) continue;
For the above I get the warning. In order to avoid it, I do
Objects.requireNonNull(items.get(item)).getPrice() != 0
The above works but it's not clean and anyway, I just checked that the item exists so for sure it's not null.
Is there a cleaner way? Thanks
Here is the full line of code:
if (!Utils.getInstance().items.containsKey(item.getId()) || Objects.requireNonNull(Utils.getInstance().items.get(item.getId())).getPrice() == 0) continue;
if (!Utils.getInstance().items.containsKey(item.getId()) || Objects.requireNonNull(Utils.getInstance().items.get(item.getId())).getPrice() == 0) continue;
That's quite a feat for a code!
You make to many logic in a single line.You need to divide it to a more readable one.
Let's simplify your code,
First, remove the requireNonNull. So it will be like this:
if (!Utils.getInstance().items.containsKey(item.getId()) || Utils.getInstance().items.get(item.getId()).getPrice() == 0) continue;
Second, extract Utils.getInstance().items to a single variable. So, it will be like this (Here I assume you're using a Map with HashMap):
// assuming a HashMap
HashMap items = Utils.getInstance().items;
if (!items.containsKey(item.getId()) || items.get(item.getId()).getPrice() == 0) continue;
Third, we extract the key as a single variable:
// assuming a HashMap
HashMap items = Utils.getInstance().items;
// assuming a string as the key
String key = item.getId();
if (!items.containsKey(key) || items.get(key).getPrice() == 0) continue;
Now, we can split the or part to this:
// assuming a HashMap
HashMap items = Utils.getInstance().items;
// assuming a string as the key
String key = item.getId();
if (!items.containsKey(key)) continue;
if(items.get(key).getPrice() == 0) continue;
the last code will gives you warning because Map.get() can return a null value. You can see from Map.get() documentation. So, we need to guard it.
Here the final version:
// assuming a HashMap
HashMap items = Utils.getInstance().items;
// assuming a string as the key
String key = item.getId();
if (!items.containsKey(key)) continue;
if(items.get(key) == null) continue;
if(items.get(key).getPrice() == 0) continue;
It maybe end up with more extra lines for your code. But it makes your code more readable and maintainable because you don't need to push your brain to hard to understand the code.
You could annotate your method/variable with #NonNull
#NonNull
fun test(){
}
#NonNull
private lateinit var test:List<String>
Maybe you should change your if condition from
if (!items.containsKey(item) || items.get(item).getPrice() != 0) continue;
to
if (items.get(item) == null || items.get(item).getPrice() != 0) continue;
You don't need to ensure that items contains the key item, just do it in following way:
Object value = items.get(item);
if (value == null || value.getPrice() != 0) continue;

Solution for very long (if statement)

I am new for programming and android development, I'm trying to make an app for length unit conversions. I used two spinner(from unit and to unit), so I need to check what user have selected in the both spinner and then return the value. My problem is I have got very long if statement, so I wonder if there is better solution for this.
Sorry for my poor english, I hope you understand what I mean.
here is the function for length:
public double lengthConversion() {
double res = 0.0;
num = Double.parseDouble(editTextNum.getText().toString());
// first spinner is mm, second spinner is mm
if (posFrom == 0 && posTo == 0) {
res = num;
} else if (posFrom == 0 && posTo == 1) { //second spinner is cm
res = num / 10;
} else if (posFrom == 0 && posTo == 2) { // dm
res = num / 100;
} else if (posFrom == 0 && posTo == 3) { // m
res = num / 1000;
} else if (posFrom == 0 && posTo == 4) { // km
res = num / 1000000;
}
if (posFrom == 1 && posTo == 0) {
....
} else if (posFrom == 1 && posTo == 1) {
....
} else if (posFrom == 1 && posTo == 2) {
....
} else if (posFrom == 1 && posTo == 3) {
....
} else if (posFrom == 1 && posTo == 4) {
....
}
.
.
.
if (posFrom == 4 && posTo == 0) {
...
} else if (posFrom == 4 && posTo == 1) {
...
} else if (posFrom == 4 && posTo == 2) {
...
} else if (posFrom == 4 && posTo == 3) {
...
} else if (posFrom == 4 && posTo == 4) {
...
}
return res;
}
and that is the string array I use:
<string-array name="array_length">
<item>mm</item>
<item>cm</item>
<item>dm</item>
<item>m</item>
<item>km</item>
</string-array>
In your first else if tree, posTo is really just a power of ten, so make the calculation instead of passing it through all those if else statements.
if (posFrom == 0)
res = num / Math.Pow(10, posTo);
All of your other units:
<string-array name="array_length">
<item>mm</item>
<item>cm</item>
<item>dm</item>
<item>m</item>
<item>km</item>
</string-array>
are just variations on powers of ten, so perform a further calculation adjusting your values based on the selected units (compared to a reference unit, probably meters), and you should need no more than 5 cases or if elses.
You can have an enum with the base unit (meter for instance).
Then you can have each other units (kms, mms, etc) as fields of that enum. I was going to draw up an example but there's an answer that does this well:
https://stackoverflow.com/a/17549248/447842
You can use the nested switch:
Switch(posFrom)
{
case 0 :
switch(posTo)
{
case 0: /*do*/ break;
case 1: /*do*/ break;
}
break;
case 1:
switch(postTo)
{
...
}
break;
...
default: /*how did i land here?*/
}
Sounds like you are doing unit conversion.
Now assuming pos 0 = mm, pos 1 = cm and so on.
int myFrom = posFrom;
int myTo = posTo;
if(myFrom == 4) then myFrom = 6;
if(myTo== 4) then myTo= 6;
num = res * math.pow(10, myFrom - myTo);
realize 1km = 1000000mm that's why when pos = 4, you need to change it to 6 since 10^6 = 1000000

getFromLocation using GPS

Can anyone tell me what is going wrong here. I am trying to obtain the address using reverse geocoding..`
if (locationGPS != null) {
list = geocoder.getFromLocation(locationGPS.getLatitude(),
locationGPS.getLongitude(), 3);
if (list != null) {
if (list.size() > 0) {
strZipcode = list.get(0).getPostalCode();
strAdminArea = list.get(0).getAdminArea();
strLocality = list.get(0).getLocality();
strAddressLine = list.get(0).getAddressLine(0);
Log.d(TAG, "list of address: "+ list);
Log.d(TAG, "Data: "+ mobileDataEnabled);
Log.d(TAG, "Data: "+ mobile);
int count = 0;
while ((strZipcode == null || strAdminArea == null
|| strLocality == null || (strAddressLine == null || strAddressLine == "USA"))
&& count < list.size()) {
strZipcode = list.get(count).getPostalCode();
strAdminArea = list.get(count).getAdminArea();
strLocality = list.get(count).getLocality();
strAddressLine = list.get(count)
.getAddressLine(count);
count++;
}`
This thing works fine and gives out the right address. But sometimes it gives out null for the all of the values which i am trying to retrieve despite the fact that i have a check in place for null values.. Am i missing something here?
Reverse Geocoder does not always return a value. It sounds weird but this is the way it is. F0r example if you hit for address 5 times, you won't be lucky enough to get response for all hits. You may get 3 instead. So workaround may be, instead of hitting geocoder one at a time, try looping your request to 2 or 3 times or more, one of the requests will work hopefully.

String array index error

I use the following method, but every time i use it i got error.
I cant figure out why because i perfrom this checking
if(unWanted == null || unWanted[0] == null)
The error is in this code:
unWanted[0] == null
but if i do only
if(unWanted == null)
It doest not see unWaned as null.
Thank for helping :)
the error code:
05-12 06:24:41.293: E/AndroidRuntime(24373): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.workoutlog/com.example.workoutlog.AddWorkOutPage}: java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
My method:
public void checking(){
DataBaseMain data = new DataBaseMain(this);
data.open();
String[] unWanted = data.getAllUnwantedExercies();
data.close();
if(unWanted == null || unWanted[0] == null)
Toast.makeText(this, "good", Toast.LENGTH_LONG).show();
else
Toast.makeText(this, "bad", Toast.LENGTH_LONG).show();
The method to get the String array from my DB.
public String[] getAllUnwantedExercies() {
Cursor c = ourDatabase.query(true, TABLE_NAME, new String[] {COLUMN_NOT_ON_LIST_EXERCISE}, null, null, COLUMN_NOT_ON_LIST_EXERCISE, null, null, null);
int dayExercise = c.getColumnIndex(COLUMN_NOT_ON_LIST_EXERCISE);
if(c.getCount() < 1)
return null;
int f = 0;
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()){
if(c.getString(dayExercise) != null && c.getString(dayExercise).equals("") == false)
f++;
}
String[] list = new String[f];
int j = 0;
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()){
if(c.getString(dayExercise) != null && c.getString(dayExercise).equals("") == false){
list[j] = c.getString(dayExercise);
j++;
}
}
return list;
}
unWanted[0] == null
It's clear that your array has no values in it. Attempting to reference the first index of an array of length 0, as explained in your stack trace, is a run time error.
unWanted == null
This doesn't work because the array object itself is not null.
A work around
A simple solution here is, at the end of your function, check the length of the array. If it is 0, you know it has no values, and you can return null.
if(list.length == 0)
{
return null;
}
else
{
return list;
}
or more concisely:
return list.length == 0? null:list;
Then when you get your array back from your function, all you need to do is test to check if the array is null.
if(unWanted == null)
{
// Array is empty.
}
Maybe just change this line:
if(unWanted == null || unWanted[0] == null)
By this one:
if(unWanted.length <= 0)
unWanted[0] == null
Here you are trying to check the first position of your array is null or not. Instead of this check your array size is 0 or not.
if(unWanted.length==0){
// your code
}
I hope this will help you.
You need to check that the length is greater than 0. It is not null because you are returning a list albeit an empty list. So it isn't null but also doesn't have a length
unWanted is not null does not mean you can reference it is first element by using unWanter[0] because it might be an empty array.

if condition on array

if i have
int win[][] ={{1,2,3},{4,5,6},{7,8,9},{1,4,7},{2,5,8},{3,6,9},{1,5,9},{3,5,7}};
Can I put condition in this way?
if(((win[0][0]) && (win[0][1]) && (win[0][2]))||
((win[1][0]) && (win[1][1]) && (win[1][2]))||
((win[2][0]) && (win[2][1]) && (win[2][2]))||
((win[3][0]) && (win[3][1]) && (win[3][2]))||
((win[4][0]) && (win[4][1]) && (win[4][2]))||
((win[5][0]) && (win[5][1]) && (win[5][2]))||
((win[6][0]) && (win[6][1]) && (win[6][2]))||
((win[7][0]) && (win[7][1]) && (win[7][2]))||
((win[8][0]) && (win[8][1]) && win[8][2])))
Your array is 8x3, means last element will be win[7][2]. So calling win[8][0] will throw an ArrayIndexOutOfBounds exception. If you correct this error, your code will work. Hope this helps.
For a clearer version of this, why not try:
for(int i = 0; i < 8; i++) {
if(win[i][0] && win[i][1] && win[i][2]) {
doStuff();
break;
}
}
If your aim is completely confuse the reader - you can

Categories

Resources