diff --git a/app/src/main/java/de/kuschku/quasseldroid/service/AndroidHeartBeatRunner.kt b/app/src/main/java/de/kuschku/quasseldroid/service/AndroidHeartBeatRunner.kt
index bb44fb01c39d2191ef19153b7830bda34fbed1a2..65ec1ea482f8275f48db9fe52e7bd6e9cbfddd93 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/service/AndroidHeartBeatRunner.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/service/AndroidHeartBeatRunner.kt
@@ -3,31 +3,39 @@ package de.kuschku.quasseldroid.service
 import android.os.Handler
 import de.kuschku.libquassel.protocol.message.SignalProxyMessage
 import de.kuschku.libquassel.session.HeartBeatRunner
-import de.kuschku.libquassel.session.Session
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.Companion.log
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.INFO
 import org.threeten.bp.Duration
 import org.threeten.bp.Instant
 
-class AndroidHeartBeatRunner(
-  private val session: Session,
-  private val handler: Handler
-) : HeartBeatRunner {
+class AndroidHeartBeatRunner : HeartBeatRunner {
+  private val handler = Handler()
   private var running = true
   private var lastHeartBeatReply: Instant = Instant.now()
   private var lastHeartBeatSend: Instant = Instant.now()
 
+  private var closeCallback: (() -> Unit)? = null
+  private var heartbeatDispatchCallback: ((SignalProxyMessage.HeartBeat) -> Unit)? = null
+
+  override fun setCloseCallback(callback: (() -> Unit)?) {
+    this.closeCallback = callback
+  }
+
+  override fun setHeartbeatDispatchCallback(callback: ((SignalProxyMessage.HeartBeat) -> Unit)?) {
+    this.heartbeatDispatchCallback = callback
+  }
+
   override fun start() {
     if (running) {
       val duration = Duration.between(lastHeartBeatReply, lastHeartBeatSend).toMillis()
       if (duration > TIMEOUT) {
         log(INFO, "Heartbeat", "Ping Timeout: Last Response ${duration}ms ago")
-        session.close()
+        closeCallback?.invoke()
       } else {
         log(INFO, "Heartbeat", "Sending Heartbeat")
         val now = Instant.now()
         lastHeartBeatSend = now
-        session.dispatch(SignalProxyMessage.HeartBeat(now))
+        heartbeatDispatchCallback?.invoke(SignalProxyMessage.HeartBeat(now))
       }
       handler.postDelayed(::start, DELAY)
     }
@@ -35,6 +43,8 @@ class AndroidHeartBeatRunner(
 
   override fun end() {
     running = false
+    setCloseCallback(null)
+    setHeartbeatDispatchCallback(null)
   }
 
   override fun setLastHeartBeatReply(time: Instant) {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/service/AsyncBackend.kt b/app/src/main/java/de/kuschku/quasseldroid/service/AsyncBackend.kt
index 29791d8e70ecb82db032e3d46421eee3988d8c56..cc2ef12ed43492e9aff998a48fac5beb67657386 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/service/AsyncBackend.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/service/AsyncBackend.kt
@@ -25,9 +25,14 @@ import de.kuschku.libquassel.util.compatibility.HandlerService
 
 class AsyncBackend(
   private val handler: HandlerService,
-  private val backend: Backend,
-  private val disconnectCallback: () -> Unit
+  private val backend: Backend
 ) : Backend {
+  private var disconnectCallback: (() -> Unit)? = null
+
+  fun setDisconnectCallback(callback: (() -> Unit)?) {
+    this.disconnectCallback = callback
+  }
+
   override fun updateUserDataAndLogin(user: String, pass: String) {
     handler.backend {
       backend.updateUserDataAndLogin(user, pass)
diff --git a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt
index 428c988944b835809b43f8af62af8a233f66b245..210607ba0ad3e35b98f186b206de115a78f2e06c 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt
@@ -21,7 +21,6 @@ package de.kuschku.quasseldroid.service
 
 import android.content.*
 import android.net.ConnectivityManager
-import android.os.Handler
 import android.text.SpannableString
 import androidx.core.app.RemoteInput
 import androidx.lifecycle.Observer
@@ -259,56 +258,72 @@ class QuasselService : DaggerLifecycleService(),
 
   private lateinit var certificateManager: QuasselCertificateManager
 
-  private val backendImplementation = object : Backend {
+  class BackendImplementation : Backend {
+    var service: QuasselService? = null
+
     override fun updateUserDataAndLogin(user: String, pass: String) {
-      accountDatabase.accounts().findById(accountId)?.let { old ->
-        accountDatabase.accounts().save(old.copy(user = user, pass = pass))
-        sessionManager.login(user, pass)
+      service?.apply {
+        accountDatabase.accounts().findById(accountId)?.let { old ->
+          accountDatabase.accounts().save(old.copy(user = user, pass = pass))
+          sessionManager.login(user, pass)
+        }
       }
     }
 
-    override fun sessionManager() = sessionManager
+    override fun sessionManager() = service!!.sessionManager
 
     override fun connectUnlessConnected(address: SocketAddress, user: String, pass: String,
                                         reconnect: Boolean) {
-      sessionManager.ifDisconnected {
-        this.connect(address, user, pass, reconnect)
+      service?.apply {
+        sessionManager.ifDisconnected {
+          connect(address, user, pass, reconnect)
+        }
       }
     }
 
     override fun connect(address: SocketAddress, user: String, pass: String, reconnect: Boolean) {
-      disconnect()
-      sessionManager.connect(
-        clientData, trustManager, hostnameVerifier, address, user to pass, reconnect
-      )
+      service?.apply {
+        disconnect()
+        sessionManager.connect(
+          clientData, trustManager, hostnameVerifier, address, user to pass, reconnect
+        )
+      }
     }
 
     override fun reconnect() {
-      sessionManager.reconnect()
+      service?.apply {
+        sessionManager.reconnect()
+      }
     }
 
     override fun disconnect(forever: Boolean) {
-      sessionManager.disconnect(forever)
+      service?.apply {
+        sessionManager.disconnect(forever)
+      }
     }
 
     override fun requestConnectNewNetwork() {
-      sessionManager.session.flatMap(ISession::liveNetworkAdded).firstElement().flatMap { id ->
-        sessionManager.session.flatMap(ISession::liveNetworks)
-          .map { it[id] }
-          .flatMap { network ->
-            network.liveInitialized
-              .filter { it }
-              .map { network }
-          }.firstElement()
-      }.toLiveData().observe(this@QuasselService, Observer {
-        it?.requestConnect()
-      })
+      service?.apply {
+        sessionManager.session.flatMap(ISession::liveNetworkAdded).firstElement().flatMap { id ->
+          sessionManager.session.flatMap(ISession::liveNetworks)
+            .map { it[id] }
+            .flatMap { network ->
+              network.liveInitialized
+                .filter { it }
+                .map { network }
+            }.firstElement()
+        }.toLiveData().observe(this, Observer {
+          it?.requestConnect()
+        })
+      }
     }
   }
 
+  private val backendImplementation = BackendImplementation()
+
   private val handlerService = AndroidHandlerService()
 
-  private val asyncBackend = AsyncBackend(handlerService, backendImplementation, ::stopSelf)
+  private val asyncBackend = AsyncBackend(handlerService, backendImplementation)
 
   @Inject
   lateinit var database: QuasselDatabase
@@ -316,14 +331,17 @@ class QuasselService : DaggerLifecycleService(),
   @Inject
   lateinit var accountDatabase: AccountDatabase
 
-  private val connectivityReceiver = object : BroadcastReceiver() {
+  class CustomConnectivityReceiver : BroadcastReceiver() {
     override fun onReceive(context: Context?, intent: Intent?) {
       if (context != null && intent != null) {
         connectivity.onNext(Unit)
       }
     }
+
+    val connectivity = PublishSubject.create<Unit>()
   }
-  private val connectivity = PublishSubject.create<Unit>()
+
+  private val connectivityReceiver = CustomConnectivityReceiver()
 
   private fun disconnectFromCore() {
     getSharedPreferences(Keys.Status.NAME, Context.MODE_PRIVATE).editCommit {
@@ -334,6 +352,9 @@ class QuasselService : DaggerLifecycleService(),
   override fun onCreate() {
     super.onCreate()
 
+    backendImplementation.service = this
+    asyncBackend.setDisconnectCallback(::stopSelf)
+
     translatedLocale = LocaleHelper.setLocale(this)
 
     certificateManager = QuasselCertificateManager(database.validityWhitelist())
@@ -345,12 +366,13 @@ class QuasselService : DaggerLifecycleService(),
       QuasselBacklogStorage(database),
       notificationBackend,
       handlerService,
-      { session: Session -> AndroidHeartBeatRunner(session, Handler()) },
-      ::disconnectFromCore,
-      ::initCallback,
+      ::AndroidHeartBeatRunner,
       CrashHandler::handle
     )
 
+    sessionManager.setDisconnectFromCore(::disconnectFromCore)
+    sessionManager.setInitCallback(::initCallback)
+
     clientData = ClientData(
       identifier = "${resources.getString(R.string.app_name)} ${BuildConfig.FANCY_VERSION_NAME}",
       buildDate = Instant.ofEpochSecond(BuildConfig.GIT_COMMIT_DATE),
@@ -377,7 +399,7 @@ class QuasselService : DaggerLifecycleService(),
       }
     })
 
-    connectivity
+    connectivityReceiver.connectivity
       .delay(200, TimeUnit.MILLISECONDS)
       .throttleFirst(1, TimeUnit.SECONDS)
       .toLiveData()
@@ -446,6 +468,10 @@ class QuasselService : DaggerLifecycleService(),
 
     unregisterReceiver(connectivityReceiver)
 
+    sessionManager.dispose()
+    asyncBackend.setDisconnectCallback(null)
+    backendImplementation.service = null
+
     notificationHandle?.let { notificationManager.remove(it) }
     super.onDestroy()
   }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/service/ServiceBoundActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/util/service/ServiceBoundActivity.kt
index 7444675033efef794b85b757e2fc0c9c46af9944..fe5176f84a899f0d91973068acaf61dfec2bd99e 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/service/ServiceBoundActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/service/ServiceBoundActivity.kt
@@ -133,6 +133,7 @@ abstract class ServiceBoundActivity :
 
   override fun onDestroy() {
     lifecycle.removeObserver(connection)
+    connection.context = null
     super.onDestroy()
   }
 
diff --git a/lib/src/main/java/de/kuschku/libquassel/connection/CoreConnection.kt b/lib/src/main/java/de/kuschku/libquassel/connection/CoreConnection.kt
index 8d42465c81b8a637dfd78017a0e4111ca729292d..bd2e3832d18c487fe1479f3b062be0ef3f5ba23a 100644
--- a/lib/src/main/java/de/kuschku/libquassel/connection/CoreConnection.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/connection/CoreConnection.kt
@@ -49,20 +49,29 @@ import javax.net.ssl.SSLSession
 import javax.net.ssl.X509TrustManager
 
 class CoreConnection(
-  private val handler: ProtocolHandler,
   private val clientData: ClientData,
   private val features: Features,
   private val trustManager: X509TrustManager,
   private val hostnameVerifier: HostnameVerifier,
   private val address: SocketAddress,
-  private val handlerService: HandlerService,
-  private val securityExceptionCallback: (QuasselSecurityException) -> Unit,
-  private val exceptionCallback: (Throwable) -> Unit
+  private val handlerService: HandlerService
 ) : Thread(), Closeable {
   companion object {
     private const val TAG = "CoreConnection"
   }
 
+  private var handler: ProtocolHandler? = null
+  private var securityExceptionCallback: ((QuasselSecurityException) -> Unit)? = null
+  private var exceptionCallback: ((Throwable) -> Unit)? = null
+
+  fun setHandlers(handler: ProtocolHandler?,
+                  securityExceptionCallback: ((QuasselSecurityException) -> Unit)?,
+                  exceptionCallback: ((Throwable) -> Unit)?) {
+    this.handler = handler
+    this.securityExceptionCallback = securityExceptionCallback
+    this.exceptionCallback = exceptionCallback
+  }
+
   private val exceptionHandler = UncaughtExceptionHandler { thread, throwable ->
     log(WARN, TAG, thread.name, throwable)
   }
@@ -157,6 +166,7 @@ class CoreConnection(
       setState(ConnectionState.CLOSED)
       channel?.flush()
       channel?.close()
+      setHandlers(null, null, null)
       interrupt()
     } catch (e: Throwable) {
       log(WARN, TAG, "Error encountered while closing connection: $e")
@@ -239,12 +249,12 @@ class CoreConnection(
       } while (cause != null && exception == null)
       if (exception != null) {
         close()
-        securityExceptionCallback(exception)
+        securityExceptionCallback?.invoke(exception)
       } else {
         if (!closed) {
           log(WARN, TAG, "Error encountered in connection", e)
           log(WARN, TAG, "Last sent message: ${MessageRunnable.lastSent.get()}")
-          exceptionCallback(e)
+          exceptionCallback?.invoke(e)
         }
         close()
       }
@@ -258,7 +268,7 @@ class CoreConnection(
       )
       handlerService.backend {
         try {
-          handler.handle(msg)
+          handler?.handle(msg)
         } catch (e: Throwable) {
           log(WARN, TAG, "Error encountered while handling sigproxy message", e)
           log(WARN, TAG, msg.toString())
@@ -277,7 +287,7 @@ class CoreConnection(
       HandshakeVariantMapSerializer.deserialize(dataBuffer, features.negotiated)
     )
     try {
-      handler.handle(msg)
+      handler?.handle(msg)
     } catch (e: Throwable) {
       log(WARN,
           TAG, "Error encountered while handling handshake message", e)
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BacklogManager.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BacklogManager.kt
index de63bc96eaaab952989c1f8eddba30644edfaa20..d111394cce385e3cbdef5dbf9297b016afbc2669 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BacklogManager.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BacklogManager.kt
@@ -22,17 +22,22 @@ package de.kuschku.libquassel.quassel.syncables
 import de.kuschku.libquassel.protocol.*
 import de.kuschku.libquassel.quassel.syncables.interfaces.IBacklogManager
 import de.kuschku.libquassel.session.BacklogStorage
-import de.kuschku.libquassel.session.Session
+import de.kuschku.libquassel.session.ISession
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.Companion.log
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.DEBUG
 
 class BacklogManager(
-  private val session: Session,
+  var session: ISession,
   private val backlogStorage: BacklogStorage
-) : SyncableObject(session, "BacklogManager"), IBacklogManager {
+) : SyncableObject(session.proxy, "BacklogManager"), IBacklogManager {
   private val loading = mutableMapOf<BufferId, (List<Message>) -> Boolean>()
   private val loadingFiltered = mutableMapOf<BufferId, (List<Message>) -> Boolean>()
 
+  override fun deinit() {
+    super.deinit()
+    session = ISession.NULL
+  }
+
   init {
     initialized = true
   }
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt
index 62695bcecb345e3b22531d3ac015fb878f77a00f..235aa911c0395e1e8a7ee63bc7d886671634074b 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt
@@ -31,9 +31,14 @@ import io.reactivex.Observable
 import io.reactivex.subjects.BehaviorSubject
 
 class BufferSyncer constructor(
-  private val session: ISession,
+  var session: ISession,
   private val notificationManager: NotificationManager?
 ) : SyncableObject(session.proxy, "BufferSyncer"), IBufferSyncer {
+  override fun deinit() {
+    super.deinit()
+    session = ISession.NULL
+  }
+
   fun lastSeenMsg(buffer: BufferId): MsgId = _lastSeenMsg[buffer] ?: 0
   fun liveLastSeenMsg(buffer: BufferId): Observable<MsgId> = live_lastSeenMsg.map {
     markerLine(buffer)
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewManager.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewManager.kt
index 12e475f26a08e44972f0fc9a215d974ec552fe41..83979dfbdb5daf4bf65ac48fbccd91bd01d6feec 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewManager.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewManager.kt
@@ -87,4 +87,8 @@ class BufferViewManager constructor(
       bufferViewConfig.handleBuffer(info, bufferSyncer, unhide)
     }
   }
+
+  override fun deinit() {
+    _bufferViewConfigs.values.map(BufferViewConfig::deinit)
+  }
 }
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManager.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManager.kt
index c411d25ab5d94e7b669d5dd2aac83797b94a7cc0..1c1dcb05b55bb8043329c27d12efb1d9f6a150a6 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManager.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManager.kt
@@ -30,11 +30,16 @@ import io.reactivex.subjects.BehaviorSubject
 import java.io.Serializable
 
 class IgnoreListManager constructor(
-  private val session: ISession,
+  var session: ISession,
   proxy: SignalProxy
 ) : SyncableObject(proxy, "IgnoreListManager"), IIgnoreListManager {
   constructor(session: Session) : this(session, session)
 
+  override fun deinit() {
+    super.deinit()
+    session = ISession.NULL
+  }
+
   override fun toVariantMap(): QVariantMap = mapOf(
     "IgnoreList" to QVariant.of(initIgnoreList(), Type.QVariantMap)
   )
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt
index fb1dbf08117c23fa5c03eeb68a97f0b4bc9353d9..de985864fb7e26b975cdd8b1e64164fba7e31863 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt
@@ -51,7 +51,9 @@ class RpcHandler(
   override fun passwordChanged(ignored: Long, success: Boolean) {
   }
 
-  override fun disconnectFromCore() = session.disconnectFromCore()
+  override fun disconnectFromCore() {
+    session.disconnectFromCore?.invoke()
+  }
 
   override fun objectRenamed(classname: ByteBuffer, newname: String, oldname: String) {
     session.renameObject(classname.deserializeString(StringSerializer.UTF8) ?: "", newname, oldname)
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/SyncableObject.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/SyncableObject.kt
index a86753f4313fd43a12f2b2a99a2ce90d82c30668..d9a4147a16c31633197471c4bdeaf86c9e25b7f6 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/SyncableObject.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/SyncableObject.kt
@@ -25,7 +25,7 @@ import io.reactivex.Observable
 import io.reactivex.subjects.BehaviorSubject
 
 abstract class SyncableObject(
-  override val proxy: SignalProxy,
+  override var proxy: SignalProxy,
   final override val className: String
 ) : ISyncableObject {
   final override var objectName: String = ""
@@ -53,5 +53,9 @@ abstract class SyncableObject(
     }
   }
 
+  override fun deinit() {
+    this.proxy = SignalProxy.NULL
+  }
+
   override fun toString() = "${identifier.first}:${identifier.second}"
 }
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/ISyncableObject.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/ISyncableObject.kt
index 16308a69012aecd679585f500d70a3c3c97a259e..5f75128bf49ee944306e712ab5a7548eea1d315e 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/ISyncableObject.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/ISyncableObject.kt
@@ -43,6 +43,7 @@ interface ISyncableObject {
     SYNC("update", ARG(properties, Type.QVariantMap))
   }
 
+  fun deinit()
   fun init() {}
 
   fun fromVariantMap(properties: QVariantMap) = Unit
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/BacklogStorage.kt b/lib/src/main/java/de/kuschku/libquassel/session/BacklogStorage.kt
index 275c24db7b43dd8495c3b8fb838e77482952700f..e122de5c0c471d59189cdb94087f48e56fb2143d 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/BacklogStorage.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/BacklogStorage.kt
@@ -23,10 +23,10 @@ import de.kuschku.libquassel.protocol.BufferId
 import de.kuschku.libquassel.protocol.Message
 
 interface BacklogStorage {
-  fun updateIgnoreRules(session: Session)
+  fun updateIgnoreRules(session: ISession)
 
-  fun storeMessages(session: Session, vararg messages: Message)
-  fun storeMessages(session: Session, messages: Iterable<Message>)
+  fun storeMessages(session: ISession, vararg messages: Message)
+  fun storeMessages(session: ISession, messages: Iterable<Message>)
 
   fun clearMessages(bufferId: BufferId, idRange: IntRange)
 
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/HeartBeatRunner.kt b/lib/src/main/java/de/kuschku/libquassel/session/HeartBeatRunner.kt
index d59696be0b6fb9bc06efb7df8b74d067729d288b..966f666e0e9dac606f428d8cf74fac3d19d60712 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/HeartBeatRunner.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/HeartBeatRunner.kt
@@ -1,8 +1,12 @@
 package de.kuschku.libquassel.session
 
+import de.kuschku.libquassel.protocol.message.SignalProxyMessage
 import org.threeten.bp.Instant
 
 interface HeartBeatRunner {
+  fun setCloseCallback(callback: (() -> Unit)?)
+  fun setHeartbeatDispatchCallback(callback: ((SignalProxyMessage.HeartBeat) -> Unit)?)
+
   fun start()
   fun end()
 
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/JavaHeartBeatRunner.kt b/lib/src/main/java/de/kuschku/libquassel/session/JavaHeartBeatRunner.kt
index b5ae349a6e2fe2a3ce4ee9e83ff1953d5937d49f..76f32a5b9d8e9467cdb13478cf09f42922fc1b61 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/JavaHeartBeatRunner.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/JavaHeartBeatRunner.kt
@@ -6,22 +6,31 @@ import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.INFO
 import org.threeten.bp.Duration
 import org.threeten.bp.Instant
 
-class JavaHeartBeatRunner(
-  private val session: Session
-) : Thread(), HeartBeatRunner {
+class JavaHeartBeatRunner : Thread(), HeartBeatRunner {
   private var running = true
   private var lastHeartBeatReply: Instant = Instant.now()
 
+  private var closeCallback: (() -> Unit)? = null
+  private var heartbeatDispatchCallback: ((SignalProxyMessage.HeartBeat) -> Unit)? = null
+
+  override fun setCloseCallback(callback: (() -> Unit)?) {
+    this.closeCallback = callback
+  }
+
+  override fun setHeartbeatDispatchCallback(callback: ((SignalProxyMessage.HeartBeat) -> Unit)?) {
+    this.heartbeatDispatchCallback = callback
+  }
+
   override fun start() {
     while (running) {
       val now = Instant.now()
       val duration = Duration.between(lastHeartBeatReply, now).toMillis()
       if (duration > TIMEOUT) {
         log(INFO, "Heartbeat", "Ping Timeout: Last Response ${duration}ms ago")
-        session.close()
+        closeCallback?.invoke()
       } else {
         log(INFO, "Heartbeat", "Sending Heartbeat")
-        session.dispatch(SignalProxyMessage.HeartBeat(now))
+        heartbeatDispatchCallback?.invoke(SignalProxyMessage.HeartBeat(now))
       }
       Thread.sleep(DELAY)
     }
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/ObjectStorage.kt b/lib/src/main/java/de/kuschku/libquassel/session/ObjectStorage.kt
index b4bb5cdd01bd925d1b5e3e2d88d6e1940906ea06..a1a753c03462f9a9326aea3e3c878993a232711e 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/ObjectStorage.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/ObjectStorage.kt
@@ -27,7 +27,13 @@ import de.kuschku.libquassel.quassel.exceptions.ObjectNotFoundException
 import de.kuschku.libquassel.quassel.syncables.interfaces.ISyncableObject
 import de.kuschku.libquassel.util.helpers.removeIfEqual
 
-class ObjectStorage(private val proxy: SignalProxy) {
+class ObjectStorage(private var proxy: SignalProxy) {
+  fun deinit() {
+    proxy = SignalProxy.NULL
+    objectTree.values.forEach(ISyncableObject::deinit)
+    objectTree.clear()
+  }
+
   private val objectTree: MutableMap<Pair<String, String>, ISyncableObject> = HashMap()
 
   fun add(obj: ISyncableObject) {
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt b/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt
index 7255cf2fb810be9f5241c2410599627e734b4f7d..8775eb8f1d50e19de8e5a8d3d5bd71d10a0baf47 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt
@@ -193,6 +193,7 @@ abstract class ProtocolHandler(
     if (syncableObject == null)
       return
 
+    syncableObject.deinit()
     objectStorage.remove(syncableObject)
     toInit.remove(syncableObject)
   }
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/Session.kt b/lib/src/main/java/de/kuschku/libquassel/session/Session.kt
index 6e44916642fd56341ef969d51a097e9226338cd6..9f9867bda743b0976bc61c916cef965e922ebe36 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/Session.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/Session.kt
@@ -45,9 +45,9 @@ class Session(
   backlogStorage: BacklogStorage,
   private val notificationManager: NotificationManager?,
   private var userData: Pair<String, String>,
-  heartBeatFactory: (Session) -> HeartBeatRunner,
-  val disconnectFromCore: () -> Unit,
-  private val initCallback: (Session) -> Unit,
+  heartBeatFactory: () -> HeartBeatRunner,
+  val disconnectFromCore: (() -> Unit)?,
+  private val initCallback: ((Session) -> Unit)?,
   exceptionHandler: (Throwable) -> Unit
 ) : ProtocolHandler(exceptionHandler), ISession {
   override val objectStorage: ObjectStorage = ObjectStorage(this)
@@ -58,15 +58,12 @@ class Session(
     get() = coreConnection.sslSession
 
   private val coreConnection = CoreConnection(
-    this,
     clientData,
     features,
     trustManager,
     hostnameVerifier,
     address,
-    handlerService,
-    ::handle,
-    ::handleConnectionError
+    handlerService
   )
   override val state = coreConnection.state
 
@@ -107,9 +104,12 @@ class Session(
 
   override val lag = BehaviorSubject.createDefault(0L)
 
-  private val heartBeatThread = heartBeatFactory(this)
+  private val heartBeatThread = heartBeatFactory()
 
   init {
+    heartBeatThread.setCloseCallback(::close)
+    heartBeatThread.setHeartbeatDispatchCallback(::dispatch)
+    coreConnection.setHandlers(this, ::handle, ::handleConnectionError)
     coreConnection.start()
   }
 
@@ -247,7 +247,7 @@ class Session(
   }
 
   override fun onInitDone() {
-    initCallback(this)
+    initCallback?.invoke(this)
     for (config in bufferViewManager.bufferViewConfigs()) {
       for (info in bufferSyncer.bufferInfos()) {
         config.handleBuffer(info, bufferSyncer)
@@ -283,12 +283,28 @@ class Session(
     super.close()
 
     heartBeatThread.end()
-
     coreConnection.close()
 
+    objectStorage.deinit()
+
+    aliasManager.deinit()
+    bufferSyncer.deinit()
+    bufferViewManager.deinit()
+    coreInfo.deinit()
+    dccConfig.deinit()
+    ignoreListManager.deinit()
+    highlightRuleManager.deinit()
+    ircListHelper.deinit()
+    networkConfig.deinit()
+    backlogManager.deinit()
+
+    rpcHandler = null
+
     certManagers.clear()
     identities.clear()
+    live_identities.onNext(Unit)
     networks.clear()
+    live_networks.onNext(Unit)
   }
 
   fun join() {
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt b/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt
index 9fd414ee340e1b9270e843902eb76e6f978e25cd..4c7d4448b24aa2ede4c7520c5a50128c2efa609c 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt
@@ -32,6 +32,7 @@ import de.kuschku.libquassel.util.helpers.or
 import io.reactivex.BackpressureStrategy
 import io.reactivex.Flowable
 import io.reactivex.Observable
+import io.reactivex.disposables.Disposable
 import io.reactivex.functions.BiFunction
 import io.reactivex.subjects.BehaviorSubject
 import javax.net.ssl.X509TrustManager
@@ -41,11 +42,20 @@ class SessionManager(
   private val backlogStorage: BacklogStorage,
   private val notificationManager: NotificationManager?,
   val handlerService: HandlerService,
-  private val heartBeatFactory: (Session) -> HeartBeatRunner,
-  private val disconnectFromCore: () -> Unit,
-  private val initCallback: (Session) -> Unit,
+  private val heartBeatFactory: () -> HeartBeatRunner,
   private val exceptionHandler: (Throwable) -> Unit
 ) {
+  private var disconnectFromCore: (() -> Unit)? = null
+  private var initCallback: ((Session) -> Unit)? = null
+
+  fun setDisconnectFromCore(callback: (() -> Unit)?) {
+    this.disconnectFromCore = callback
+  }
+
+  fun setInitCallback(callback: ((Session) -> Unit)?) {
+    this.initCallback = callback
+  }
+
   fun close() = session.or(lastSession).close()
 
   private var lastClientData: ClientData? = null
@@ -85,29 +95,27 @@ class SessionManager(
       Triple(t1, t2.first, t2.second)
     })
 
+  val disposables = mutableListOf<Disposable>()
+
   init {
     log(INFO, "Session", "Session created")
 
-    state.subscribe {
+    disposables.add(state.subscribe {
       if (it == ConnectionState.CONNECTED) {
         lastSession.close()
       }
-    }
+    })
 
-    error.subscribe {
+    disposables.add(error.subscribe {
       hasErrored = true
-    }
+    })
 
     // This should preload them
     Invokers
   }
 
-  fun ifDisconnected(closure: (ISession) -> Unit) {
-    state.or(ConnectionState.DISCONNECTED).let {
-      if (it == ConnectionState.CLOSED || it == ConnectionState.DISCONNECTED) {
-        closure(inProgressSession.value)
-      }
-    }
+  fun login(user: String, pass: String) {
+    inProgressSession.value.login(user, pass)
   }
 
   fun connect(
@@ -189,7 +197,20 @@ class SessionManager(
     inProgressSession.onNext(ISession.NULL)
   }
 
-  fun login(user: String, pass: String) {
-    inProgressSession.value.login(user, pass)
+  fun ifDisconnected(closure: (ISession) -> Unit) {
+    state.or(ConnectionState.DISCONNECTED).let {
+      if (it == ConnectionState.CLOSED || it == ConnectionState.DISCONNECTED) {
+        closure(inProgressSession.value)
+      }
+    }
+  }
+
+  fun dispose() {
+    setDisconnectFromCore(null)
+    setInitCallback(null)
+    for (disposable in disposables) {
+      if (!disposable.isDisposed)
+        disposable.dispose()
+    }
   }
 }
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselBacklogStorage.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselBacklogStorage.kt
index c429c43767245dd387af037810c21203bad03371..241d12bb3c085718447bfd01fcde09ccb2bb9695 100644
--- a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselBacklogStorage.kt
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselBacklogStorage.kt
@@ -24,10 +24,9 @@ import de.kuschku.libquassel.protocol.Message
 import de.kuschku.libquassel.quassel.syncables.IgnoreListManager
 import de.kuschku.libquassel.session.BacklogStorage
 import de.kuschku.libquassel.session.ISession
-import de.kuschku.libquassel.session.Session
 
 class QuasselBacklogStorage(private val db: QuasselDatabase) : BacklogStorage {
-  override fun updateIgnoreRules(session: Session) {
+  override fun updateIgnoreRules(session: ISession) {
     db.message().save(
       *db.message().all().map {
         it.copy(ignored = isIgnored(session, it))
@@ -35,10 +34,10 @@ class QuasselBacklogStorage(private val db: QuasselDatabase) : BacklogStorage {
     )
   }
 
-  override fun storeMessages(session: Session, vararg messages: Message) =
+  override fun storeMessages(session: ISession, vararg messages: Message) =
     storeMessages(session, messages.asIterable())
 
-  override fun storeMessages(session: Session, messages: Iterable<Message>) {
+  override fun storeMessages(session: ISession, messages: Iterable<Message>) {
     db.message().save(*messages.map {
       QuasselDatabase.MessageData(
         messageId = it.messageId,