How do I know if a Uri is empty? - android

I have an application where I need to be able to let the user decide how to put a picture profile, (camera or gallery). I have only one variable of type "Uri" but I do not understand how to reset it and make it EMPTY, or check if it is EMPTY. Because when I choose a picture I have to have the ability to change the photo if you do not like the one just put. I have tested as
if (followUri.equals (Uri.EMPTY)) {...}
but the application crashes with a null point exception.

Just check that Empty URI is not equal to followUri, this check includes check by null:
if (!Uri.EMPTY.equals(followUri)) {
//handle followUri
}

If the Uri itself is null then calling followUri.equals(Object) will result in a NPE. A better solution:
if (followUri != null && !followUri.equals(Uri.EMPTY)) {
//doTheThing()
} else {
//followUri is null or empty
}

If your app crashes with an NPE at that stage followUri is most likely null.
Also Uri objects are immutable, see here http://developer.android.com/reference/android/net/Uri.html so you cannot "reset" it.

Check if followUri != null and after that you can check if it is empty, you get NPE because followUri is null don't you? After that you can set followUri = Uri.EMPTY

Just to add my 2 cents a null Uri is not treated as Empty. The value of Uri.EMPTY is "". Which can cause some confusion if you are expecting null == Uri.EMPTY to be trueenter code here. A small kotlin code snippet as well :
fun isUriEmpty(uri: Uri?):Boolean{
return uri == null || uri == Uri.EMPTY
}

Related

List find method finds nothing, but let is called (?!)

i have the following code:
myList.find { it.code == item.bin }.let {
// 1
} ?: run {
// 2
}
I would expect that, if item is found, I enter block 1 , otherwise block 2 ;
But instead I enter block 1 in all cases, and if nothing is found , it is null
Android studio seems aware of this, as the block 2 is grey (it is code never called), but I can't figure why
Please may someone explain why ?
null is still a value so it makes sense that the first block is run. it'd be the same as if you ran null.let { println("hey!") }.
you probably want to run let with a null check: myList.find { it.code == item.bin }?.let { ... }. this way the block will only run if there is indeed a value being returned that is not null.
You are using classic dot call operator ., this operator is not allowed on nullable types. If you want to call this operator on nullable type insert !! before operator, but if you call it on null it throws NullPointerException
You have to use Kotlins safe call operator ?., which call method when insatce is not null and when is it returns null.
?: operator is called Elvis operator and it returns first value if it is not null, else it returns second value.
So just change in your code dot operator . to safe call operator ?.:
myList.find { it.code == item.bin }.let {
// 1
} ?: run {
// 2
}

LiveMutableData and copies update to same value?

I have a MutableLiveData variable in my AppRepository which is updated and contains my data. This I have no issues with. I also have the following observable to trigger a UI update with the data it holds in my onCreateView function:
viewModel.projectWithContent.observe(viewLifecycleOwner, {
pwc = it
counterList = it.counterList
})
When I tap either to increase or decrease the counter count and then try to push the update to my Room database, it skips it. I have the following check currently:
if(counterList != null) {
try {
for(counter: Counter in counterList!!) {
if(counter.counter_count != pwc?.counterList!![
pwc?.counterList!!.indexOf(counter)
].counter_count) {
Log.i(LOG_TAG, "Hello")
} else {
Log.i(LOG_TAG, "Goodbye")
}
}
} catch(e: IndexOutOfBoundsException) {
e.printStackTrace()
}
}
It'll always go to Goodbye.
Now. If I put the following just below try
Log.i(LOG_TAG, "PWC: ${pwc?.counterList!![0].counter_count}, " +
"CPWC: ${counterList!![0].counter_count}," +
"VMPWC: ${viewModel.projectWithContent.value?.counterList!![0].counter_count}")
It provides the following output:
PWC: 70, CPWC: 70,VMPWC: 70
Is this a side effect of what I'm doing or?
Thanks
Like #Tenfour04 says, your condition is actually checking they don't match, so "Goodbye" is the output when they do match.
If you don't mind (this is a little long), I just want to recommend some stuff because I feel like you're making life hard for yourself with all the null-checking that's going on - the logic of the code was really hard to read, and I'm guessing that's why you didn't notice the flipped logic too!
First: the ? null safety stuff (and !! which is the opposite of safe, never use it unless you know you have good reason) is there because you have nullable variable types. Normally the IDE would smart cast them to non-null once you've done a null check (like on your first line) - but because they're vars, they can be changed at any time.
That means that a variable that wasn't null before could be now, so you're forced to null-check every single time you access it. But even if the types weren't nullable, because they're vars, they can still change, and the thing you were looking at a moment ago is something different now.
The simple solution is to just make a new variable:
val counters = counterList
if (counters != null) {
...
}
// or if you want to use one of kotlin's scope functions
counterList?.let { counters ->
...
}
Because that new one is a val, it's not going to change what it's pointing at! Once it's null-checked, it's always going to be non-null, so you don't need to use ? anymore.
You have a couple of variables to make - you want to make sure pwc isn't null, and also their counterLists. A quick way to do that is with pwc?.counterList - if pwc is null, it will return null. Otherwise it will move to the next step, and return counterList, which may be null. (Using !! is saying that it definitely never will be null, in which case it shouldn't be nullable at all!)
And you don't actually care about pwc anyway - you're just comparing its counterList to the other, so why don't we pare it back to just those?
val counters = counterList
val pwcCounters = pwc?.counterList
if (counters != null && pwcCounters != null) {
try {
for(counter: Counter in counters) {
if(counter.counter_count != pwcCounters[
pwcCounters.indexOf(counter)
].counter_count) {
Log.i(LOG_TAG, "Hello")
} else {
Log.i(LOG_TAG, "Goodbye")
}
}
} catch(e: IndexOutOfBoundsException) {
e.printStackTrace()
}
}
There's more we could do here, but just by cleaning up those nulls and using the specific variables we want to work with, does that feel easier to read? And more importantly, easier to understand what's happening and what could happen?
Might be worth throwing it in a function too, stops the call site getting cluttered with these temp variables:
fun doThing(counters: List<Counter>?, pwcCounters: List<Counter>?) {
if (counters == null || pwcCounters == null) return
// do the stuff
}
// when you want to do the thing:
doThing(counterList, pwc?.counterList)
So all your null checking is out of the way, your "temp variables" are the fixed parameters passed to the function, it's all nice and neat.
I know this is a long post for such a short bit of code, but it's a good habit to get into - if you're writing code where you're working with nullable vars and you're wrestling with the null safety system, or you keep repeating yourself to access a particular variable nested inside another object, you can make things a lot easier for yourself! You can imagine how wild this could all get for more complex code.
Also if you care, this is how I'd personally write it, if it helps!
fun doThing(counters: List<Counter>?, pwcCounters: List<Counter>?) {
if (counters == null || pwcCounters == null) return
// for (counter in Counters) is fine too I just like this version
counters.forEach { counter ->
// find returns the first item that matches the condition, or null if nothing matches,
// so no need to handle any exceptions, just handle the potential null!
// (this is a really common Kotlin pattern, lots of functions have a "returns null on failure" version)
val pwcCounter = pwcCounters.find { it == counter }
// remember pwcCounter can be null, so we have to use ? to access its count safely.
// If it evaluates to null, the match just fails
if (counter.count == pwcCounter?.count) Log.i(LOG_TAG, "Hello")
else Log.i(LOG_TAG, "Goodbye")
}
}
I also renamed counter_count to just count since it's a property on a Counter anyway. I feel like counter.count is easier to read than counter.counter_count, y'know? It's the little things

Is there an idiomatic way to deal with null value in if else branch?

I'm kind of thinking if there is a cleaner way to express this code.
return if (response.isSuccessful()) {
response.body
else null
What I'm referring to here is the else null part. An almost similar statement in Kotlin would be
return response?.let {
it.body
} ?: null
But in the above situation, we can write the same code without the ?: null part and the compiler will automatically assign null value. So why does Kotlin's if statement require a null else part?
return if (response.isSuccessful()) {
response.body
}
So why does Kotlin's if statement require a null else part?
Because the compiler does not know that you want to return null in the else branch. For all it knows, you might want to do something else, such as return a random number, or return some default value, or throw an exception.
But in the above situation, we can write the same code without the ?: null part and the compiler will automatically assign null value.
That is because the safe call (?.) evaluates to null if the receiver is null.
I know your question is more about kolin rather than finding a way of doing something like that, but maybe takeIf is close to what you want.
return response.takeIf { it.isSuccessful() }?.body

Why is my null check unreachable?

In the following example i have an nullable property userId. I would like throw an Exception if it null. Android studio is telling me the code block inside if(userId == null) is unreachable. Can anyone explain why this is unreachable?
return Observable.create<Optional<UserEntity>> { it ->
val userId: String? = firebaseAuth.currentUser?.uid
if(userId == null){
it.onError(throw RuntimeException("Unauthorised"))
it.onComplete()
}else{
//Do something
}
}
Ok... I see... in fact it is the following line that contains the unreachable code:
it.onError(throw RuntimeException("Unauthorised"))
The reason: you throw your exception immediately and not when there occurs an error in processing. In fact the onError itself becomes unreachable.
onError however, needs the exception to throw as passed argument, so what you rather want is something like:
it.onError(RuntimException("Unauthorised"))
i.e. omit the throw.

Android Null Checker

I have a program that relates to a database. I start out my program by inserting a row using the following command.
long id = db.insertMajor(null, null, null, null);
it works perfect. I than alter the information but lets ignore that since for the time being I commented out all those lines. Now I want to check and see if it is null which is should be. If it is not null than I would like to check a checkbox. if it is null than I want to leave the box unchecked. So far I have this line to test.
String change = db.getMajorTitle(value).getString(1);
if (change.equals(null)) {
filled = false;
}
the filled boolean will check the box or not. If the database field is filled or not I always get a checkmark. Whats wrong?
UPDATE:
Since no one has figure it out I will post most of my code to try and help figure it out. I have also reset my emulator to ensure there is not problems with corrupted data.
chk1.setChecked(checker(1));
chk2.setChecked(checker(2));
chk3.setChecked(checker(3));
chk4.setChecked(checker(4));
}
boolean checker(int value){
DBAdapter db = new DBAdapter(this);
boolean filled = false;
db.open();
for (int i = 1; i <= 4; i++) {
String change = db.getMajorTitle(value).getString(1);
if (change == null) {
filled = false;
}else{
filled = true;
}
}
db.close();
return filled;
}
If someone copies this and it works can you please tell me what might be wrong with my emulator or eclipse or whatever. Thanks everyone for there input.
FINISHED:
I noticed that at another part in my program I changed null to "". I would like to thank everyone for being right and showing me different ways to code it.
You really don't need if statements for this.
filled = (change != null);
if (change.equals(null)) {
If change instance is not null, the above condition always returns false. Read Object equality constraints for more info.
If you want to check against null use
if( change == null) {
// change is null, update filled field
} else {
// change is not null, update filled field
}
If the database field is filled or not
I always get a checkmark. Whats wrong?
I guess that you would have initialized the filled field as true and never set it as false since your if condition always returns false or throws NullPointerException.
User ExceptionHandling mechanism. then you will succeed. Like
try {
if(change!=null)
{
//do ur work,if not null
}
else
{
// do some thing
}
}catch(NullPointerException e)
{
//do ur work,if null.
}

Categories

Resources