class FTPClientLiveData : MutableLiveData<FTPClient>() {
private var isConnecting = false
private var lock = ReentrantLock()
override fun onActive() {
val client = value
if (client == null || !client.isConnected) {
try {
lock.lock()
if (!isConnecting) {
isConnecting = true
//async connection task
}
} finally {
lock.unlock()
}
}
}
override fun onInactive() {
val client = value
if (client != null) {
try {
client.logout()
client.disconnect()
} catch (e: Throwable) {
e.printStackTrace()
}
}
}
override fun setValue(value: FTPClient?) {
try {
lock.lock()
isConnecting = false
super.setValue(value)
} finally {
lock.unlock()
}
}
}
class FTPClientLiveData : BaseLiveDate<FTPClient>() {
override fun onActive() {
val coroutineResult = value
if (coroutineResult == null || coroutineResult.status != CoroutineResult.Status.LOADING ||
(coroutineResult.data != null && coroutineResult.error == null && !coroutineResult.data.isConnected)
) {
runCoroutine(this) {
return@runCoroutine FtpBrowserInteractor.connect(
App.instance.appPref.ftpServer,
App.instance.appPref.ftpPort,
App.instance.appPref.ftpLogin,
App.instance.appPref.ftpPassword
)
}
}
}
override fun onInactive() {
val coroutineResult = value
coroutineResult?.let {
if (coroutineResult.data != null) {
try {
coroutineResult.data.logout()
coroutineResult.data.disconnect()
} catch (e: Throwable) {
e.printStackTrace()
}
}
}
}
override fun setValue(value: CoroutineResult<FTPClient>?) {
//no external setting
}
}
open class BaseLiveDate<T> : MutableLiveData<CoroutineResult<T>>() {
protected fun <T> runCoroutine(resultLiveData: MutableLiveData<CoroutineResult<T>>, block: suspend () -> T) {
value = CoroutineResult(
CoroutineResult.Status.LOADING,
null,
null
)
GlobalScope.launch(Dispatchers.IO) {
try {
val result = block()
resultLiveData.postValue(
CoroutineResult(
CoroutineResult.Status.COMPLETED,
result,
null
)
)
} catch (exception: Exception) {
resultLiveData.postValue(
CoroutineResult(
CoroutineResult.Status.COMPLETED,
null,
exception
)
)
}
}
}
}