DisposableObserver<> is not subtype of Observer<> - kotlin

I am trying to convert this RxJava/RxAndroid lesson to RxKotlin/RxAndroid.
At the method at Example5 I get error from picture
My getNotesObservable() function is:
fun getNotesObservable(): Observable<Note>{
val notes: List<Note> = prepareNotes()
return Observable.create {
for (note in notes) {
if (!it.isDisposed){ // onNext only if observable is not disposed
it.onNext(note)
}
}
if (!it.isDisposed) {
it.onComplete()
}
}
}
and part with error is:
disposable.add(
getNotesObservable().subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map{
it.note = it.note.toUpperCase()
}
.subscribeWith(getNotesObserver())
)
So, what's should I change in my code?

All that I needed was return statement (from picture below)
Thanks for answer

Related

Kotlin Flow two dependant request but return the first

I have two functions, the first one that returns a Result with a model, and the second one that returns a Result with another model.
fun flow1(): Flow<Result<Model1>>
fun flow2(id: String): Flow<Result<Model2>>
What i want is went the flow1() call is success, then do the flow2() call and some logic when is success but at the end return the flow1() result.
And for the moment i just trying something like this:
flow1().flatMapLatest { flow1Result ->
flow1Result.onSuccess {
flow2(it.id).map { flow2Result ->
flow2Result.onSuccess {
//Some logic
}
}
}.onFailure {
// return error
}
}
I have two problems the first one that inside the flatMapLatest give an error because say that i return a Result instead of a Flow. And how i can return the Flow1 result?
Thank you!
Trying something similar to this response Chain kotlin flows depends on Result state
I guess you need something like this
fun main() {
flow1().flatMapLatest { flow1Result ->
// should return flow with flow1Result element emited
flow1Result
.onSuccess {
// flow<flow1Result>, that we return
flow2(it.id).map { flow2Result ->
flow2Result
.onSuccess{
TODO("some logic")
}.onFailure{
// only emit flow1Result when flow2Result = Success
throw RuntimeError()
}
// convert flow<flow2Result> to flow <flow1Result>
flow1Result
}
}
.onFailure {
// there can be other flow<flow1Result>
throw RuntimeError()
}
}
}

Transform Single<List<Maybe<Book>>> to Single<List<Book>>

could someone help, please?
I have these functions
fun getBooks(): Single<List<Book>> {
return getCollections()
.map {
it.map(::collectonToBook)
}
}
fun getCollections(): Single<List<Collection>> {
return db.fetchCollections()
.filter(::isBook)
}
fun collectonToBook(collection: Collection): Maybe<Book> {
return collection.toBook()
}
The problem is getBooks returns Single<List<Maybe<Book>>> when I need Single<List<Book>>. Can I do that inside the stream without calling blockingGet?
Try this:
getCollections() // Single<List<Collection>>
.flattenAsFlowable { it } // Flowable<Collection>
.concatMapMaybe { collectonToBook(it) } // Flowable<Book>
.toList() // Single<List<Book>>
In words, unwrap the inner List into its elements, transform the Collection into a Book, concatenate their respective Maybe sources, then finally collect the Books into a List again.

Why does the author wrap tasksRepository.refreshTasks() with viewModelScope.launch?

The following code is from the project.
The function of tasksRepository.refreshTasks() is to insert data from remote server to local DB, it's a time consuming operation.
In class TasksViewModel, asksRepository.refreshTasks() is wrapped with viewModelScope.launch{}, it means launch and careless.
1: How can I guarantee tasksRepository.observeTasks().distinctUntilChanged().switchMap { filterTasks(it) } to return the latest result?
2: I don't know how distinctUntilChanged() work, will it keep listening to return the latest result in whole Lifecycle ?
3: What's happened if I use tasksRepository.observeTasks().switchMap { filterTasks(it) } instead of tasksRepository.observeTasks().distinctUntilChanged().switchMap { filterTasks(it) }
Code
class TasksViewModel(..) : ViewModel() {
private val _items: LiveData<List<Task>> = _forceUpdate.switchMap { forceUpdate ->
if (forceUpdate) {
_dataLoading.value = true
viewModelScope.launch {
tasksRepository.refreshTasks()
_dataLoading.value = false
}
}
tasksRepository.observeTasks().distinctUntilChanged().switchMap { filterTasks(it) }
}
...
}
class DefaultTasksRepository(...) : TasksRepository {
override suspend fun refreshTask(taskId: String) {
updateTaskFromRemoteDataSource(taskId)
}
private suspend fun updateTasksFromRemoteDataSource() {
val remoteTasks = tasksRemoteDataSource.getTasks()
if (remoteTasks is Success) {
tasksLocalDataSource.deleteAllTasks()
remoteTasks.data.forEach { task ->
tasksLocalDataSource.saveTask(task)
}
} else if (remoteTasks is Result.Error) {
throw remoteTasks.exception
}
}
override fun observeTasks(): LiveData<Result<List<Task>>> {
return tasksLocalDataSource.observeTasks()
}
}
switchMap - The returned LiveData delegates to the most recent LiveData created by calling switchMapFunction with the most recent value set to source, without changing the reference. Doc
Yes, it'll keep listening to return the latest result in whole Lifecycle. distinctUntilChanged creates a new LiveData object that does not emit a value until the source LiveData value has been changed. The value is considered changed if equals() yields false.
Yes you can use that too but it'll keep emitting the values even the values are the same as the last emitted value.
e.g. first emitted value is ["aman","bansal"] and the second is the same ["aman","bansal"] which you don't want to emit since the values are same. So you use distinctUntilChanged to make sure it won't emit the same value until changed.
I hope this helped.

Kotlin ?.let + ?:run + CompletableFuture unexpected behaviour

Here is the code, it runs as expected, no exception
fun main() {
var mayBeEmptyString: String?
mayBeEmptyString = "1";
mayBeEmptyString?.let {
println("Inside let")
} ?: run {
throw RuntimeException("Inside run")
}
}
Output:
Inside let
And here is the code that I am not able to understand how it works:
fun main() {
var mayBeEmptyString: String?
mayBeEmptyString = "1";
mayBeEmptyString?.let {
// println("Inside let")
CompletableFuture.runAsync{ println("Inside let")}.join()
} ?: run {
throw RuntimeException("Inside run")
}
}
Output:
Inside let
Exception in thread "main" java.lang.RuntimeException: Inside run
at com.test.TestKt.main(test.kt:15)
at com.test.TestKt.main(test.kt)
Can anyone explain what is going on here? Thank you.
runAsync is meant for running a task that doesn't return a value, so you get a CompletableFuture<Void>, and attempting to read its value with get or join will give you null.
You then make this null result of join the result of your let block, which will cause your run block to be executed.
Because CompletableFuture.join() return null value cause
mayBeEmptyString?.let {
// println("Inside let")
CompletableFuture.runAsync{ println("Inside let")}.join()
}
will be null
and run { } will be executed

Create a callback function with another callback inside

My apologies for the bad title, I'm fairly new to callbacks and I'm not sure how to explain what I'm trying to achieve.
I have a class called MyClass that has a function connectToService inside of it.
The function connectToService does some calculations and then calls a function with a callback, like this:
fun connectToService() {
//Whatever calculations
val a = 7
var b = 3
var c = a + b
val token = MyToken()
token.actionCallback = object: SuperSecretObject {
override fun onSuccess(asyncActionToken: MyToken) {
c++
}
override fun onFailure(asyncActionToken: MyToken) {
c--
}
}
}
I want to create another class, YourClass which creates an object of MyClass and then calls the connectToService function. When the connectToService function finishes either the onSuccess or onFailurefunctions, I want to do something depending on which one was triggered (something different each time, thats why I can't put it inside the onSuccess or onFailure blocks of code).
Something like this:
//Inside `yourClass`
private fun myFunc() {
val yourClassObj = YourClass()
youClassObj.connectToService {
if(onSuccess)
reinventTheWheel()
else
squareIt()
}
youClassObj.connectToService {
combAWatermelon()
}
youClassObj.connectToService {
sharpenMyHammer()
}
}
Is this possible? If so, how can I achieve it? If it's not, what would be the closest solution to this requirement?
EDIT:
More detailed information has been requested, so while I can't provide exact details, I'll do my best to explain what's going on.
I'm basically working on a library to simplify petitions. For example, MQTT petitions. This is something tht resembles what I want to achieve:
/**
* Subscribes to a list of topics and handles the results
*/
fun subscribe(client: MqttAndroidClient, list: MutableList<String>, onMsg: ((String, MqttMessage)->Unit)?=null, conLost: ((Throwable)->Unit)?=null, delComp: ((IMqttDeliveryToken)->Unit)?=null) {
if (client.isConnected) { //Assert connection
for(x in list.iterator()) { //Subscribe to events
client.subscribe(x, 0)
}
client.setCallback(object : MqttCallback {
override fun connectionLost(cause: Throwable) { //Lost connection
Log.i("TAG", "Connection lost")
conLost?.let { it(cause) }
}
#Throws(java.lang.Exception::class)
override fun messageArrived(topic: String, message: MqttMessage) { //Arrived message
Log.i("TAG", "Message arrived: topic => $topic, message => $message")
onMsg?.let { it(topic, message) }
}
override fun deliveryComplete(token: IMqttDeliveryToken) { //Delivery complete
Log.i("TAG", "Delivery complete")
delComp?.let { it(token) }
}
})
}
}
The messageArrived function must have a behaviour that can be customized depending on the app it's being used on.
For example, on one app I want the onMsg() function to be like this:
when(topic) {
"firstTopic" -> {
localVariable++
}
"secondTopic" -> {
localMethod()
}
"thirdTopic" -> {
localClass.variable.method()
}
}
If I'm using it on an Android device, I'd like to be able to update the interface, doing Android API calls, etc.
I'm not sure I got your question correctly. I think what you are looking for is passing lambdas.
fun connectToService(onSucc: ()->Unit, onFail: ()->Unit) {
//Whatever calculations
MyToken().actionCallback = object: SuperSecretObject {
override fun onSuccess(asyncActionToken: MyToken) {
onSucc()
}
override fun onFailure(asyncActionToken: MyToken) {
onFail()
}
}
}
Then you can call the function like this:
connectToService({ /* Something */ }, { /* Something else */ })