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

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;

Related

checking if variables are empty otherwise get the value

I want to get value from several variables for example user1, user2, user3, user4.
how to check if variables are empty otherwise get the value and ignore variables that empty.
how I achieve this?, and sorry for newbie question...
if I do this
if(user1 != null && user2!= null && user3 != null && user4 != null){
user1.getText(); // or v1 = user1.value();
user2.getText(); // or v2 = user2.value();
user3.getText(); // or v3 = user3.value();
user4.getText(); // or v4 = user4.value();
}
which I dont want to do that, I just want to get the variable which had value in it and save it in array
Try with the following code.
ArrayList<String> listItems=new ArrayList<String>();
if(user1!=null)
{
listItems.add(user1.getText());
}
if(user2!=null)
{
listItems.add(user2.getText());
}
if(user3!=null)
{
listItems.add(user3.getText());
}
if(user4!=null)
{
listItems.add(user4.getText());
}
String [] arrayData = listItems.toArray(new String[listItems.size()]);
Note:You can also use isEmpty() method instead of checking for not a null value.
You mean a null check?
Value v1;
Value v2;
if (user1 != null) {
v1 = user1.value();
}
if (user2 != null) {
v2 = user2.value();
}
...etc
If you are dealing with String values then you may want to check the empty or null using TextUtils.isEmpty(str) API
public static boolean isEmpty (CharSequence str) Returns true if the string is null or 0-length.
if(user1!=null && !TextUtils.isEmpty(user1.getText()){
//not empty or null
}

Why is this code throwing NumberFormatException Invalid int: ""?

I'm trying to get it to if a user doesn't enter a value in the EditText boxes, the initial value is set to 0 (to prevent the crash error NumberFormatException Invalid int: "") which is thrown assuming because there is no integer value to read, since the user didn't input one in this case.
I've tried a number of things most recently this:
String boozeAmount = boozeConsumed.getText().toString();
if (boozeAmount == "" || boozeAmount == null){
boozeConsumed.setText("0");
boozeAmount = boozeConsumed.getText().toString();
}
int boozeOz = Integer.parseInt(boozeAmount) * 12;
double beerCalc = boozeOz * 4 * 0.075;
But it seems to still throw the same error, not sure why the int values aren't being set to 0?
Throwing error on
int boozeOz = Integer.parseInt(boozeAmount) * 12;
if (boozeAmount == "" || boozeAmount == null){
It can be easily deduced from your explanation that this particular if statement is returning true, that's why your string value is not being set to "0".
Strings in Java are not primitive, i.e they cannot be compared with the comparator ==.
You need to use the method equals to compare strings, as in boozeAmount.equals("").
Apache Commons has a StringUtils utility that can check if strings are null or empty.
Check out isEmpty and isBlank.
you dont compare strings with == you compare it with .equals()
Change it to:
if (boozeAmount.equals("") || boozeAmount == null)
Although it's probably safest to also do:
if (...)
{
// just set it to zero and skip even trying to parse
}
else
{
// do the actual parsing
}
Whenever you are fetching a string value from the EditText always trim that variable to avoid any white spaces from EditText.
String boozeAmount = boozeConsumed.getText().toString().trim(); // apply Trim
// Always compare strings with `equals()` method in Java & Android
if ( boozeAmount.equals( "" ) || boozeAmount == null )
{
boozeConsumed.setText("0");
boozeAmount = boozeConsumed.getText().toString();
}
int boozeOz = Integer.parseInt(boozeAmount) * 12;
double beerCalc = boozeOz * 4 * 0.075;
You could check if it's blank and then fill it with 0 and then get the input.
Also, always compare string values with .equals and use .trim() to get rid of whitespace so that it's recognized as invalid input as well.
if (boozeConsumed.getText().toString().trim().equals("")) {
// if (boozeConsumed.length() == 0) { // doesn't consider spaces though
boozeConsumed.setText("0");
}
String boozeAmount = boozeConsumed.getText().toString();
int boozeOz = Integer.parseInt(boozeAmount) * 12;
double beerCalc = boozeOz * 4 * 0.075;
Or just do this, because you don't need to parse it to an integer if you know there's nothing there:
String boozeAmount = boozeConsumed.getText().toString();
int boozeOz = 0;
double beerCalc = 0;
if (boozeAmount.trim().equals("") || boozeAmount == null){
boozeConsumed.setText("0");
boozeAmount = boozeConsumed.getText().toString();
} else {
// only parse it if there's something there
boozeOz = Integer.parseInt(boozeAmount) * 12;
beerCalc = boozeOz * 4 * 0.075;
}

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.

Parse big xml file in android

In my application there is a search option. If the user enters a search value, I have to get a value from the webservice. I am getting a large webservice value. In my webservice string values are coming. I am getting like <> like xml character entity reference like. I want to replace all characters and parse xml. Can anybody tell me how to do this and give an example?
I tried with StringBuffer for unescapexml character, I am getting out of memory error
public String unescapeXML(String str) {
if (str == null || str.length() == 0)
return "";
StringBuffer buf = new StringBuffer();
int len = str.length();
for (int i = 0; i < len; ++i) {
char c = str.charAt(i);
if (c == '&') {
int pos = str.indexOf(";", i);
if (pos == -1) { // Really evil
buf.append('&');
} else if (str.charAt(i + 1) == '#') {
int val = Integer.parseInt(str.substring(i + 2, pos), 16);
buf.append((char) val);
i = pos;
} else {
String substr = str.substring(i, pos + 1);
if (substr.equals("&"))
buf.append('&');
else if (substr.equals("<"))
buf.append('<');
else if (substr.equals(">"))
buf.append('>');
else if (substr.equals("""))
buf.append('"');
else if (substr.equals("&apos;"))
buf.append('\'');
else if (substr.equals(" "))
buf.append(" ");
else
// ????
buf.append(substr);
i = pos;
}
} else {
buf.append(c);
}
}
return buf.toString();
}
I tried with stream, I am not able to do it. Can anybody give an example how to do this?
You should not parse it on your own. There are better ways - SAX or DOM.
This resource contains a lot of useful inforamtion about these both ways (and code examples too): http://onjava.com/pub/a/onjava/2002/06/26/xml.html
Take a look here in order to get more details about android included parsers :
http://developer.android.com/reference/javax/xml/parsers/package-summary.html
But make your own parser with SAX is probably the best choice in your case ;)

Categories

Resources