Tinder / Scarlet

A Retrofit inspired WebSocket client for Kotlin, Java, and Android
Other
3.22k stars 236 forks source link

Multiple callbacks after toggle between onStart and onPause #152

Open james04gr opened 3 years ago

james04gr commented 3 years ago

By using Koin i create my networkModule like below

val networkModule = module {

   ......

single {
        return@single AndroidLifecycle.ofApplicationForeground(androidApplication())
    }

    single {
        return@single Scarlet.Builder()
            .webSocketFactory(get<OkHttpClient>().newWebSocketFactory(Wss))
            .lifecycle(get())  // I can create my own lifeCycle and combineWith(), for example accounts.isEmpty
            .backoffStrategy(LinearBackoffStrategy(5000))
            .addMessageAdapterFactory(GsonMessageAdapter.Factory(get()))
            .addStreamAdapterFactory(CoroutinesStreamAdapterFactory())
            .build()
            .create(FlowSocketApi::class.java)
    }
}
val lifecycleModule = module {
    single {
        return@single AppLifeCycleObserver()
    }
}

I also have an Observer class that is registered to the Application lifecycle.

class AppLifeCycleObserver :
    LifecycleObserver, KoinComponent {

    private val flowEventsObserver: LiveData<WebSocket.Event> =
        flowSocketService.observeEvents().consumeAsFlow().asLiveData()

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun onEnterForeground() {
        flowEventsObserver.observeForever { event ->
           when(event) {
            is WebSocket.Event.OnConnectionOpened<*> -> {
                println("WebSocket.Event.OnConnectionOpened")
                println(event)
            }
            is WebSocket.Event.OnMessageReceived -> {
                println("WebSocket.Event.OnMessageReceived")
                println(event.message.toString())

            }
            is WebSocket.Event.OnConnectionClosing -> {
                println("WebSocket.Event.OnConnectionClosing")
                println(event)
            }
            is WebSocket.Event.OnConnectionClosed -> {
                println("WebSocket.Event.OnConnectionClosed")
                println(event)
            }
            is WebSocket.Event.OnConnectionFailed -> {
                println("WebSocket.Event.OnConnectionFailed")
                println(event)
            }
        }
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun onEnterBackground() {

    }
}

which of course is initialized in the Application class

class MyApplication : Application() {
    private val appLifeCycleObserver: AppLifeCycleObserver by inject()

    override fun onCreate() {
        super.onCreate()

        startKoin {
            androidContext(this@MyApplication)
            modules(
                arrayListOf(networkModule,databaseModule,managersModule,repositoryModule,lifecycleModule)
            )
        }

        ProcessLifecycleOwner.get().lifecycle.addObserver(appLifeCycleObserver)
}

When the app starts, Scarlet creates a connection and onEnterForeground is triggered. So the LiveData outputs OnConnectionOpened(webSocket=okhttp3.internal.ws.RealWebSocket@6795837)

After that i press the home button so the application enters background, so the Scarlet has to cancel the current socket connection. However after relaunch the app, app gets in Foreground start, Scarlet has to reopen the connection as it does but the problem is that in my Logcat i see double times the print

OnConnectionOpened(webSocket=okhttp3.internal.ws.RealWebSocket@b87493b)
OnConnectionOpened(webSocket=okhttp3.internal.ws.RealWebSocket@b87493b)

And as i go on and do the same thing the onConnectionOpened gets multiplied...!! What is going wrong??

Korogba commented 3 years ago

Hello @james04gr, did you manage to figure out how to resolve this? I am facing a similar issue on a project I am working on.

james04gr commented 3 years ago

No...try to find another library! The guy that has this never answers!

milouk commented 3 years ago

I have the same issue, has anyone figured out a solution?

james04gr commented 3 years ago

I have the same issue, has anyone figured out a solution?

The solution is to switch to another library. Nobody takes care of this one

FreedomChuks commented 3 years ago

has this issue been fixed

whatiamdoing commented 3 years ago

after connect and disconnect to websocket, OnConnectionOpened triggered 1 more time: D/rere: WebSocket.Event.OnConnectionOpened D/rere: WebSocket.Event.OnConnectionOpened D/rere: WebSocket.Event.OnConnectionOpened D/rere: WebSocket.Event.OnConnectionOpened

Korogba commented 3 years ago

TL;DR - Ensure you call disconnect on each LifecycleRegistry object used to open the socket.

If you are listening to the lifecycle state using things classes like AndroidLifecycle.ofApplicationForeground, be careful you instantiate only a single instance per application.

Faced a similar issue and the lifecycle is tied to the application's lifecycle so it can cause the socket to reconnect even when you did not intend it to. To mitigate this, ensure the call to disconnect is called from all the LifecycleRegistry object used to open the socket.