I have bellow code which works just fine, but produces a warning:
method invocation 'cursor.close()' may produce 'java.lang.nullpointerexception'
cursor_id may not be initialized, as, e.g., your try block checks. You need to add the same validation in the finally block:
} finally {
if (cursor_id != null) {
cursor_id.close();
}
}
Related
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
}
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
How to check for a specific exception, e.g. SocketException with message "Socket closed"? We can compare strings like this:
if (exception.getMessage().equals("Socket closed"))...
but is there some more elegant method, like comparing error codes, or comparison with constant exception value?
Except if SocketException is always "Socket closed", but in docs it states that this class is a superclass for all socket exceptions, so there is more than one.
UPDATE:
I don't want to check for exception class. If I do, I would use specialized catch rather than to check tor a class explicitly:
catch (SocketException ex) { ... }
I want some more elegant method to distinct two exceptions which are instances of the same class, not by comparing strings like this:
try {
int i = 2;
if (i == 1) throw new SocketException("one");
else if (i == 2) throw new SocketException("two");
}
catch (SocketException ex) {
if (ex.getMessage().equals("one")) { ... }
}
In this particular case I throw exceptions to show what is it about, but in reality it can be code not controlled by me.
Also I noticed that exception message in one particular case method threw "Socket closed", in another different method threw "Socket is closed". So it's not so reliable to stick to the message either.
Your question has different approaches, depending on what you are trying to achieve. The simplest method for determining if you have the exception you want is to use instanceof since an Exception is a class as well, i.e.:
if (myException instanceof SocketException) {
...
}
However, you then add the requirement of the contents of the message or the possibility that the Exception thrown is actually a subclass of the Exception of interest to you. In the case of a "subclass" you can check if it is a subclass with:
if (myException instanceof SocketException &&
myException.getClass() != SocketException.class) {
// then I'm an instance of a subclass of SocketException, but not SocketExcpetion itself
}
Or conversely, only evaluate for the parent class:
if (myException instanceof SocketException &&
myException.getClass() == SocketException.class) {
// then I'm an instance of the class SocketException, and not a cubclass of SocketExcpetion!!
}
These serve as the "error codes" you seem to be looking for - the identification of the class, with certainty.
However, if you really are interested in the human-readable error contents, then the solution you have should be your implementation. That seems unlikely, but sometimes that is what is required.
You can use:
exception.getClass().getSimpleName() and compare it to SocketException
Hope this helps.
I cannot make an Android phonegap plugin work. Not even a single one of the examples I found nor my pathetic failures trying to create one by myself. I first tried with Tutorials like this one. They don't work for me. I always end up with a Cannot call method of undefined error.
So I tried something ready. Got this project from github. It's just a simple plugin to show a toast. I checked everything that i learned on the tutorials:
//the package name in the java
package com.phonegap.toast;
//my class extends Plugin and has a simple show toast method.
public class Tutorial extends Plugin {
#Override
public PluginResult execute(String cmd, JSONArray args, String callback) {
if(cmd.equals("toast"))
{
return showToast(args);
}
return null;
}
private PluginResult showToast(JSONArray args) {
final String message;
try {
message = args.getString(0);
ctx.runOnUiThread(new Runnable()
{
public void run() {
Toast myToast = Toast.makeText(ctx, message, Toast.LENGTH_SHORT);
myToast.show();
}
});
return new PluginResult(PluginResult.Status.OK);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
}
}
}
the plugin is defined in res/xml/plugins.xml
plugin name="Tutorial" value="com.phonegap.toast.Tutorial"
and no, if i put it on rex/xml/config.xml it also doesn't work
Last, the method that calls the plugin:
function createToast() {
// i also tried window.Tutorial.showToast('Hello AndroidOpen'); with no success
window.plugins.Tutorial.showToast('Hello AndroidOpen');
}
And here I get the same error again.
10-22 15:39:07.770: E/Web Console(2885): Uncaught TypeError: Cannot call method 'showToast' of undefined at file:///android_asset/www/main.js:123
Any enlightened soul can explain to me what I'm doing wrong? I've been trying this for days, with many different plugins, both my own and even this ones and I can't find out what is it.
Okay, here are a few things that are probably tripping you up. First if the config.xml file exists in res/xml then it will take precedence over plugins.xml. So you will need to add your plugin line to config.xml instead.
Make sure you are including the .js file for your Toast plugin.
Third, window.plugins has been deprecated away so you may need to modify the .js if you are using PhoneGap 2.0.0 or better. Check out my blog post on the topic. The root change is that you now need to new PluginName in your JS as it is no longer put in window.plugins by default.
For example, the flash platform provides the flash.debugger.enterDebugger() API call that does the job:
if (some_cond())
{
...
}
else
{
enterDebugger();
}
In that case, if some_cond() evaluates to false and we're in a debug session (it does nothing if we're in a normal session), then the execution will be halted at the line where enterDebugger is invoked and control given to the debugger, as if a breakpoint was set at that line.
I've looked at the android.os package but found nothing like it. Throwing an exception does the job of giving the control to the debugger, but then the code execution cannot be resumed at the spot where the exception was thrown.
Java debugging supports suspending on exceptions. You could write:
void enterDebugger() {
try {
throw new DebugException();
}
catch (DebugException e) { //no-op
}
}
And setup your IDE to suspend on caught exceptions of type DebugException.
if (someCond()) { .... }
else {
android.os.Debug.waitForDebugger();
}
See android.os.Debug.