I'm trying to display emails of users stored in firebase database.
I've this below code
snapsListView = findViewById(R.id.snapsList)
val adapter = emails?.let { ArrayAdapter(this, android.R.layout.simple_list_item_1, it) }
snapsListView?.adapter = adapter
auth.currentUser?.uid?.let { FirebaseDatabase.getInstance().getReference().child("users").child(it).child("snaps").addChildEventListener(object: ChildEventListener{
override fun onChildAdded(snapshot: DataSnapshot, previousChildName: String?) {
emails?.add(snapshot.child("from").value as String)
adapter?.notifyDataSetChanged()
try {
for(x in emails!!){
Log.i("Emails", x)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
Emails are present in the database and as per the hierrarchy also, users-> uid->snaps and snaps contains the email in "from"
Don't know what is causing this error, or how do i resolve this.
Always getting null pointer exception
By using !! operator you have asserted that emails is not null. However, Kotlin thrown runtime exception because emails is null actually. Consider replacing !! with safe-access:
emails?.let { for (x in it) Log.i("Emails", x) }
Related
I am fairly new at working with API calls in Android Studio and I'm having trouble with a block of code. It's a function that deletes a specific task item from a remote database.
Here's my code.
RepoInterface:
suspend fun deleteRemoteTask(token: String, id: Int, task: Task): Response<Task>
RepoImplementation:
override suspend fun deleteRemoteTask(token: String, id: Int, task : Task): Response<Task> = withContext(Dispatchers.IO) {
return#withContext try {
apiService.deleteTask(token, id, task)
} catch (e: Exception) {
Log.d("TAG", "deleteRemoteTask: Api Failed to run")
throw Exception(e.localizedMessage)
}
}
Repository:
val response = remote.deleteRemoteTask(token, id, task)
if (response.isSuccessful) {
local.deleteTask(response.body()!!)
return local.getTaskByID(response.body()!!.id)
} else {
throw Exception("Repo: API Call unsuccessful")
}
}
I'm confident that my interface and implementation are set up correctly, but the logic in my actual repository is a bit shaky, as I keep getting an Exception thrown. The data is coming down from the View -> Viewmodel -> UseCase -> Repo -> RepoImp -> Interface -> API.
I also have
We would need a bit more info. The flow is not well implemented but no worries we all start by a point :D, I will adapt my answer to this flow.
Let's start with:
avoiding the !! non null operator in the response.body()!!.
If you mark that the response body is not null, in case it is it will crash, local.deleteTask should receive a body response nullable parameter and should handle the possible null body.
First the first; let's wrap the complete function in Repository into a try catch, something like:
try {
val response = remote.deleteRemoteTask(token, id, task)
if (response.isSuccessful) {
local.deleteTask(response.body()!!)
return local.getTaskByID(response.body()!!.id)
} else {
throw Exception("Repo: API Call unsuccessful")
}
} catch(e: Exception) {
throw e
}
Let's check why that response is not successful, I see you throwing an Exception with a message in case the response is not successful, try to throw the Exception with the response.code(), something like:
try {
val response = remote.deleteRemoteTask(token, id, task)
if (response.isSuccessful) {
local.deleteTask(response.body()!!)
return local.getTaskByID(response.body()!!.id)
} else {
throw Exception("Repo: API Call unsuccessful, response error code: ${response.code()}")
}
} catch(e: Exception) {
throw e
}
In your RepoImplementation, let's print that Exception stack trace and log it:
override suspend fun deleteRemoteTask(token: String, id: Int, task : Task): Response<Task> = withContext(Dispatchers.IO) {
return#withContext try {
apiService.deleteTask(token, id, task)
} catch (e: Exception) {
Log.d("TAG", "deleteRemoteTask: Api Failed to run, stack trace: ${e.printStackTrace()}")
}
}
Then in the logcat you can search for the TAG and see what is going on with that response. Let me know how it goes :D
I have the following Kotlin code:
fun getAdminUser(): User {
return getAllUsers().first { it.userType == ADMIN } as User
}
If getAllUsers() doesn't have an element that matches the specified predicate, it throws a NoSuchElementException. I'm happy with this exception but would like to override the exception message to provide more context when it fails. Is it possible to do in Kotlin w/o try-catch?
You could use the firstOrNull function to achieve that.
fun getAdminUser(): User {
return (getAllUsers().firstOrNull { it.userType == ADMIN } as? User) ?: throw NoSuchElementException("Element not found")
}
Use firstOrNull to get first element or have null and use the elvis operator to throw NoSuchElementException.
fun getAdminUser(): User {
val user = getAllUsers().firstOrNull { it.userType == ADMIN } ?: throw NoSuchElementException("My custom exception message")
return user as? User ?: IllegalStateException("The element was neither null nor an instance of User class")
}
Otherwise to do it in single line you can do something like this:
fun getAdminUser(): User {
return getAllUsers().firstOrNull { it.userType == ADMIN }?.also { require(it is User) { "The element was neither null nor an instance of User class" } } ?: throw NoSuchElementException("My custom exception message")
}
According to the source of Closable.use, if an error occurs, an exception will be thrown.
public inline fun <T : Closeable?, R> T.use(block: (T) -> R): R {
var exception: Throwable? = null
try {
return block(this)
} catch (e: Throwable) {
exception = e
throw e
} finally {
when {
apiVersionIsAtLeast(1, 1, 0) -> this.closeFinally(exception)
this == null -> {}
exception == null -> close()
else ->
try {
close()
} catch (closeException: Throwable) {
// cause.addSuppressed(closeException) // ignored here
}
}
}
In most examples of Closable.use, try-catch is not used as shown below.
Why isn't error handling needed? Is it safe?
BufferedReader(FileReader("test.file")).use { return it.readLine() }
This line
BufferedReader(FileReader("test.file")).use { return it.readLine() }
is not safe. Reading and closing the reader can both throw IOExceptions, which are not RuntimeExceptions (caused by programming errors). That means leaving them uncaught exposes your app to crashing from things outside your control.
Since Kotlin doesn't have checked exceptions, the compiler won't warn you about this. To do this safely, you need to wrap it in try/catch. And if you want to handle read errors differently than close errors, you either need to have inner and outer try/catch statements:
try {
BufferedReader(FileReader("test.file")).use {
try {
return it.readLine()
catch (e: IOException) {
println("Failed to read line")
}
}
} catch (e: IOException) {
println("Failed to close reader")
}
or wrap the whole thing and extract any suppressed exceptions, but then its cumbersome to distinguish between them:
try {
BufferedReader(FileReader("test.file")).use { return it.readLine() }
} catch (e: IOException) {
val throwables = listOf(e, *e.suppressed)
for (throwable in throwables)
println(throwable.message)
}
But in practice, you're probably not going to react differently to various IOExceptions, so you can just put the one try/catch outside.
We see from Kotlin documentation what is the purpose of the use function:
Executes the given block function on this resource and then closes it
down correctly whether an exception is thrown or not.
This function closes the resource properly if the block function completed successfully or threw an exception. It is your responsibility to handle the result of the block function.
If an exception was thrown and there is a way to handle it and proceed with code execution, use a try/catch. If there is nothing to do about it and control should be passed to the caller, it is not necessary to use a try/catch.
I found some non-intuitive behavior of type inference. As a result, the semantically equivalent code works differently, depending on what information the compiler infers about function return type. It is more or less clear what is going on when you reproduce this case in a minimum unit test. But I afraid that when writing framework code, such behavior could be dangerous.
The code below illustrates the problem, and my questions are:
Why the puzzler1 call from notok1 unconditionally throws NPE? As far as I understand from the bytecode, ACONST_NULL ATHROW throws NPE right after puzzler1 call, ignoring the returned value.
Is it normal that upper bound (<T : TestData>) is ignored when compiler infers the type?
Is it a bug that NPE becomes ClassCastException if you add suspend modifier to the function? Of course, I understand that runBlocking+suspend call gives us the different bytecode, but shouldn't the "coroutinized" code be as equivalent as possible to conventional code?
Is there a way to rewrite puzzler1 code somehow, eliminating the unclearness?
#Suppress("UnnecessaryVariable", "MemberVisibilityCanBePrivate", "UNCHECKED_CAST", "RedundantSuspendModifier")
class PuzzlerTest {
open class TestData(val value: String)
lateinit var whiteboxResult: TestData
fun <T : TestData> puzzler1(
resultWrapper: (String) -> T
): T {
val result = try {
resultWrapper("hello")
} catch (t: Throwable) {
TestData(t.message!!) as T
}
whiteboxResult = result
return result // will always return TestData type
}
// When the type of `puzzler1` is inferred to TestData, the code works as expected:
#Test
fun ok() {
val a = puzzler1 { TestData("$it world") }
// the same result inside `puzzler1` and outside of it:
assertEquals("hello world", whiteboxResult.value)
assertEquals("hello world", a.value)
}
// But when the type of `puzzler1` is not inferred to TestData, the result is rather unexpected.
// And compiler ignores the upper bound <T : TestData>:
#Test
fun notok1() {
val a = try {
puzzler1 { throw RuntimeException("goodbye") }
} catch (t: Throwable) {
t
}
assertEquals("goodbye", whiteboxResult.value)
assertTrue(a is NullPointerException) // this is strange
}
// The same code as above, but with enough information for the compiler to infer the type:
#Test
fun notok2() {
val a = puzzler1 {
#Suppress("ConstantConditionIf")
if (true)
throw RuntimeException("goodbye")
else {
// the type is inferred from here
TestData("unreachable")
// The same result if we write:
// puzzler1<TestData> { throw RuntimeException("goodbye") }
}
}
assertEquals("goodbye", whiteboxResult.value)
assertEquals("goodbye", (a as? TestData)?.value) // this is stranger
}
// Now create the `puzzler2` which only difference from `puzzler1` is `suspend` modifier:
suspend fun <T : TestData> puzzler2(
resultWrapper: (String) -> T
): T {
val result = try {
resultWrapper("hello")
} catch (t: Throwable) {
TestData(t.message!!) as T
}
whiteboxResult = result
return result
}
// Do exactly the same test as `notok1` and NullPointerException magically becomes ClassCastException:
#Test
fun notok3() = runBlocking {
val a = try {
puzzler2 { throw RuntimeException("goodbye") }
} catch (t: Throwable) {
t
}
assertEquals("goodbye", whiteboxResult.value)
assertTrue(a is ClassCastException) // change to coroutines and NullPointerException becomes ClassCastException
}
// The "fix" is the same as `notok2` by providing the compiler with info to infer `puzzler2` return type:
#Test
fun notok4() = runBlocking {
val a = try {
puzzler2<TestData> { throw RuntimeException("goodbye") }
// The same result if we write:
// puzzler2 {
// #Suppress("ConstantConditionIf")
// if (true)
// throw RuntimeException("goodbye")
// else
// TestData("unreachable")
// }
} catch (t: Throwable) {
t
}
assertEquals("goodbye", whiteboxResult.value)
assertEquals("goodbye", (a as? TestData)?.value)
}
}
What is the type of throw RuntimeException("goodbye")? Well, since it never returns a value, you can use it anywhere you like, no matter what type of object is expected, and it will always typecheck. We say that it has type Nothing. This type has no values, and it is a subtype of every type. Therefore, in notok1, you have a call to puzzler1<Nothing>. The cast from the constructed TestData to T = Nothing inside puzzler1<Nothing> is unsound but unchecked, and puzzler1 ends up returning when its type signature says it shouldn't be able to. notok1 notices that puzzler1 has returned when it said it would not be able to, and immediately throws an exception itself. It's not very descriptive, but I believe the reason it throws an NPE is because something has gone "terribly wrong" if a function that can't return has returned, so the language decides the program should die as fast as possible.
For notok2, you actually do get T = TestData: one branch of the if returns Nothing, the other TestData, and the LUB of those is TestData (since Nothing is a subtype of TestData). notok2 has no reason to believe that puzzler1<TestData> cannot return, so it doesn't set up the trap to die as soon as puzzler1 returns.
notok3 has essentially the same problem as notok1. The return type, Nothing, implies that the only thing the puzzler2<Nothing> will do is throw an exception. The coroutine handling code in notok3 thus expects the coroutine to hold a Throwable and contains code to rethrow it, but does not contain code to handle an actual return value. When puzzler2 actually does return, notok3 tries to cast that TestData into a Throwable and fails. notok4 works for the same reason notok2 does.
The solution to this mess is simply not using an unsound cast. Sometimes puzzler1<T>/puzzler2<T> will be able to return a T, if the passed function in fact returns a T. But, if that function throws, they can only return a TestData, and a TestData is not a T (a T is a TestData, not the other way around). The correct signature for puzzler1 (and similarly for puzzler2) is
fun <T : TestData> puzzler1(resultWrapper: (String) -> T): TestData
Since functions are covariant in the return type, you can just get rid of the type parameter
fun puzzler1(resultWrapper: (String) -> TestData): TestData
I am a bit confused with throwing custom exceptions in Swift 3.
In C++ I can do this to immediately stop the process in the method, throw an error and handle it without proceeding further.
void foo()
{
try
{
if (a > b)
{
throw MyException();
}
DoOtherStaff();
}
catch (const MyException& e)
{
HandleError();
}
}
I am trying to implement something like this in Swift 3
enum MyError : Error
{
case myError(String)
}
func foo()
{
do
{
if (a > b)
{
throw MyError.myError("My error message");
}
DoOtherStaff();
}
catch
{
HandleError();
}
}
But it tells me me that the error is not handled because the enclosing catch is not exhaustive. Is there a way to handle it?
Thank you!
There is nothing wrong a priori with the code you showed. As a proof, just copy and paste the following into a playground (or into a class definition in an actual project):
enum MyError : Error {
case myError(String)
}
let a = 1
let b = 2
func foo() {
do {
if a > b {
throw MyError.myError("My error message")
}
doOtherStuff()
}
catch {
handleError()
}
}
func doOtherStuff() {}
func handleError() {}
That compiles and runs fine in the playground (though of course it doesn't do anything). Observe that all I did different from the code you gave was to "fill in the blanks", i.e. provide declarations of all the terms you referred to.