Kotlin -> lateinit 和 lazy 详解

lateinitlazy 详解

核心区别

特性lateinitlazy
类型可变属性修饰符 var不可变属性委托 val
初始化时机手动显式初始化,随时可变首次访问时自动初始化,之后不可变
空安全非空类型,但初始值可缺失非空类型,保证有值
适用类型不能用于基本类型(Int, Boolean等)可用于任何类型
线程安全不保证线程安全默认线程安全SYNCHRONIZED模式
检查机制使用前需确保已初始化,否则抛异常自动处理初始化,不会抛出未初始化异常

lateinit 核心用法

// 声明
class User {
    lateinit var name: String
    
    fun initialize() {
        name = "John" // 手动初始化
    }
    
    fun greet() {
        if (::name.isInitialized) { // 检查是否已初始化
            println("Hello, $name")
        }
    }
}

最佳使用场景:

  • 依赖注入
  • Activity/Fragment中的视图绑定
  • 单元测试的setUp方法中
  • 需要推迟初始化但之后可能需要修改的属性

lazy 核心用法

// 基本用法
class User {
    val name: String by lazy { 
        println("Computing name...")
        "John" // 计算并返回初始值
    }
}

// 指定线程安全模式
val expensiveData: List<Data> by lazy(LazyThreadSafetyMode.PUBLICATION) {
    loadDataFromDatabase()
}

线程安全模式:

  • SYNCHRONIZED:默认模式,线程安全,只执行一次初始化
  • PUBLICATION:多线程可能执行多次,但只有第一个结果被使用
  • NONE:不保证线程安全,适用于单线程环境,性能最好

最佳使用场景:

  • 计算开销大的属性
  • 需要根据条件计算的只读属性
  • 单例模式实现
  • 配置项和缓存数据

核心实现原理

lateinit

  • 在字节码级别,不为属性分配默认值
  • 访问前不进行空检查
  • 使用前若未初始化,抛出UninitializedPropertyAccessException

lazy

  • 内部使用SynchronizedLazyImpl等实现类
  • 持有一个初始化器函数和一个存储结果的AtomicReference
  • 首次访问时执行初始化器并缓存结果

如何选择

  • 如果属性需要在初始化后修改,使用lateinit var
  • 如果属性是只读的且可以延迟计算,使用lazy val
  • 如果处理基本类型,只能使用lazy
  • 如果在多线程环境中,优先考虑lazy
帮助我讲解代码:package com.tplink.omada.sdncontroller.base import android.app.Application import androidx.annotation.ColorRes import androidx.annotation.StringRes import androidx.databinding.Observable import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.tplink.omada.OmadaApplication import com.tplink.omada.R import com.tplink.omada.common.Event import com.tplink.omada.common.utils.safeLaunch import com.tplink.omada.controller.session.ControllerSessionManager import com.tplink.omada.controller.viewmodel.BaseViewModel import com.tplink.omada.libnetwork.controller.model.Results import com.tplink.omada.libnetwork.controller.model.SdnErrorCode import com.tplink.omada.libnetwork.controller.protocol.GeneralResponse import com.tplink.omada.libnetwork.controller.protocol.OltInnerResponse import com.tplink.omada.libnetwork.sdncontroller.model.ClientInfo import com.tplink.omada.libnetwork.sdncontroller.model.Device import com.tplink.omada.libnetwork.sdncontroller.model.DeviceType import com.tplink.omada.libnetwork.sdncontroller.model.EnumLanguageCode import com.tplink.omada.libnetwork.sdncontroller.model.LanguageType import com.tplink.omada.libnetwork.sdncontroller.model.OpenApiBatchResult import com.tplink.omada.libutility.log.Log import com.tplink.omada.sdncontroller.ExceptionHandle import com.tplink.omada.sdncontroller.SdnErrMsg import com.tplink.omada.sdncontroller.repository.ClientRepository import com.tplink.omada.sdncontroller.repository.DeviceRepository import com.tplink.omada.sdncontroller.repository.MspDeviceRepository import com.tplink.omada.sdncontroller.repository.OltRepository import com.tplink.omada.sdncontroller.ui.loading.LaunchState import com.tplink.omada.sdncontroller.ui.monitor.SdnDeviceStatus import com.tplink.omada.sdncontroller.viewmodel.mspv2.EnumQueryParameter import com.tplink.omada.sdncontroller.viewmodel.mspv2.SdnDeviceListBaseViewModel import com.tplink.omada.sdncontroller.viewmodel.settings.site.SdnControllerSiteViewModel import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.coroutineScope import java.util.Locale /** * Created by Wan Chengwenjie on 2020/1/12. */ open class SdnBaseViewModel(application: Application) : BaseViewModel(application) { val uiEvent: UIChange by lazy { UIChange() } private lateinit var repository: ClientRepository private lateinit var mspDeviceRepo: MspDeviceRepository private var clientResult: ClientInfo? = null private val callbacks = mutableListOf<Pair<Observable, Observable.OnPropertyChangedCallback>>() // controller是否支持分页获取, var supportGetDeviceByPage = false protected fun <T: Observable> T.addAutoRemoveCallback(callback: (Observable?) -> Unit) { val wrappedCallback = object : Observable.OnPropertyChangedCallback() { override fun onPropertyChanged(sender: Observable?, propertyId: Int) { callback(sender) } } addOnPropertyChangedCallback(wrappedCallback) callbacks.add(this to wrappedCallback) } override fun onCleared() {0 try { callbacks.forEach { (observable, callback) -> observable.removeOnPropertyChangedCallback(callback) } callbacks.clear() } catch (e: Exception) { Log.e("SdnBaseViewModel", e.message) } super.onCleared() } /** * 过滤请求结果,其他全抛异常, 不显示loading * @param block 请求体 * @param success 成功回调 * @param error 失败回调 */ fun <T> launchBackground( block: suspend CoroutineScope.() -> GeneralResponse<T>, success: (T) -> Unit, error: (SdnErrMsg) -> Unit = { uiEvent.showDialog.postValue(Event(it)) }) { launchOnlyResult(block, success, error, {}, false) } fun <T> launchBackground( block: suspend CoroutineScope.() -> GeneralResponse<T>, success: (T) -> Unit, error: (SdnErrMsg) -> Unit = { uiEvent.showDialog.postValue(Event(it)) }, ignoreLaunchState: Boolean = false) { launchOnlyResult(block, success, error, {}, false, ignoreLaunchState = ignoreLaunchState) } fun <T> launchManualLoading( block: suspend CoroutineScope.() -> GeneralResponse<T>, success: (T) -> Unit, error: (SdnErrMsg) -> Unit = { uiEvent.showDialog.postValue(Event(it)) }, complete: () -> Unit = {}) { viewModelScope.safeLaunch({ handleException( { block() }, { res -> executeResponse(res) { @Suppress("UNCHECKED_CAST") success(it ?: (Unit as T)) } }, { error(it) }, { complete() } ) }, { error(detachError(it)) }) } fun <T> launchOnlyResult( block: suspend CoroutineScope.() -> GeneralResponse<T>, success: (T) -> Unit, error: (SdnErrMsg) -> Unit = { uiEvent.showDialog.postValue(Event(it)) }, complete: () -> Unit = {}, isShowDialog: Boolean = true ) { launchOnlyResult(block, success, error, complete, isShowDialog, false) } /** * 过滤请求结果,其他全抛异常 * @param block 请求体 * @param success 成功回调 * @param error 失败回调 * @param complete 完成回调(无论成功失败都会调用) * @param isShowDialog 是否显示加载框 */ fun <T> launchOnlyResult( block: suspend CoroutineScope.() -> GeneralResponse<T>, success: (T) -> Unit, error: (SdnErrMsg) -> Unit = { uiEvent.showDialog.postValue(Event(it)) }, complete: () -> Unit = {}, isShowDialog: Boolean = true, ignoreLaunchState: Boolean = false ) { if(!ignoreLaunchState && OmadaApplication.getInstance().controllerSessionManager.controllerLaunchManager.controllerLaunchStateFlow.value == LaunchState.Launching) return if (isShowDialog) uiEvent.loading.postValue(Event(true)) viewModelScope.safeLaunch({ handleException( { block() }, { res -> executeResponse(res) { @Suppress("UNCHECKED_CAST") success(it ?: (Unit as T)) } }, { error(it) }, { uiEvent.loading.postValue(Event(false)) complete() } ) }, { uiEvent.loading.postValue(Event(false)) error(detachError(it)) }) } /** * 过滤请求结果,其他全抛异常 * @param block 请求体 * @param success 成功回调 * @param error 失败回调 * @param complete 完成回调(无论成功失败都会调用) * @param isShowDialog 是否显示加载框 */ fun <T> launchOnlyResultExt( block: suspend CoroutineScope.() -> GeneralResponse<T>, success: (T) -> Unit, error: (SdnErrMsg) -> Unit = { uiEvent.showDialog.postValue(Event(it)) }, complete: () -> Unit = {}, isShowDialog: Boolean = true ) { if (isShowDialog) uiEvent.loadingExt.postValue(Event(true)) viewModelScope.safeLaunch({ handleException( { block() }, { res -> executeResponse(res) { @Suppress("UNCHECKED_CAST") success(it ?: (Unit as T)) } }, { error(it) }, { if (isShowDialog) { uiEvent.loadingExt.postValue(Event(false)) } complete() } ) }, { if (isShowDialog) { uiEvent.loadingExt.postValue(Event(false)) } error(detachError(it)) }) } /** * 上一个接口如果返回的Data在某种情况下为空的 */ fun <T> launchAnyResult( block: suspend CoroutineScope.() -> GeneralResponse<T>, success: (T?) -> Unit, error: (SdnErrMsg) -> Unit = { uiEvent.showDialog.postValue(Event(it)) }, complete: () -> Unit = {}, isShowDialog: Boolean = true ) { if (isShowDialog) uiEvent.loading.postValue(Event(true)) viewModelScope.safeLaunch({ handleException( { block() }, { res -> executeResponse(res) { @Suppress("UNCHECKED_CAST") success(it) } }, { error(it) }, { uiEvent.loading.postValue(Event(false)) complete() } ) }, { uiEvent.loading.postValue(Event(false)) error(detachError(it)) }) } /** * 请求结果过滤 */ protected suspend fun <T> executeResponse( response: GeneralResponse<T>, success: suspend CoroutineScope.(T) -> Unit ) { coroutineScope { if (response.isSuccess) { success(response.result) } else { if(response.rawErrorCode == SdnErrorCode.TRANSPARENT_ERROR_CODE.code){ // 转换为InnerResponse val OLTInnerResponse = response.result as OltInnerResponse throw SdnErrMsg.fromErrorCode(SdnErrorCode.fromCode(response.rawErrorCode, OLTInnerResponse.errcode), getApp()) } if (response.rawErrorCode == SdnErrorCode.BATCH_OPENAPI_ERROR_CODE.code) { val batchOpenApiResponse = response.result as? OpenApiBatchResult batchOpenApiResponse?.response?.find { it.errorCode != SdnErrorCode.OK.code }?.let { itemResponse -> throw SdnErrMsg.fromErrorCode(SdnErrorCode.fromCode(itemResponse.errorCode ?: SdnErrorCode.UNKNOWN.code), getApp()) } } throw SdnErrMsg.fromErrorCode(SdnErrorCode.fromCode(response.rawErrorCode), getApp()) } } } /** * 请求并验证接口返回数据 * * 通过[GeneralResponse.getRawErrorCode]判断接口请求结果,并回调对应结果,同时也支持自动抛出错误,弹出对应的错误提示 * * @param repoApi 接口 * @param showDialog 是否需要显示错误码对应的弹窗 * @param success 成功的数据回调 * @param throwable 异常回调 */ protected suspend fun <T> verifyResponse( repoApi: suspend () -> GeneralResponse<T>, showDialog: Boolean = true, success: (T) -> Unit = {}, throwable: (SdnErrMsg) -> Unit = {} ) { runCatching { executeResponse(repoApi()) { success.invoke(it) } }.onFailure { val error = detachError(it) throwable.invoke(error) if (showDialog) { uiEvent.showDialog.postValue(Event(error)) } } } /** * 请求并验证接口返回数据 * * 在接口验证成功后,通过LiveData回调数据 * * @param repoApi 接口 * @param liveData 成功的数据通过此[MutableLiveData.postValue]回调,可不传 */ protected suspend fun <T, LD : MutableLiveData<T>> verifyResponseAndPost(repoApi: suspend () -> GeneralResponse<T>, liveData: LD? = null) { verifyResponse(repoApi, success = { liveData?.postValue(it) }) } /** * 异常统一处理 */ private suspend fun <T> handleException( block: suspend CoroutineScope.() -> GeneralResponse<T>, success: suspend CoroutineScope.(GeneralResponse<T>) -> Unit, error: suspend CoroutineScope.(SdnErrMsg) -> Unit, complete: suspend CoroutineScope.() -> Unit ) { coroutineScope { try { success(block()) } catch (e: Throwable) { Log.e("Launch Exception", e.toString()) e.printStackTrace() error(detachError(e)) } finally { complete() } } } fun detachError(e: Throwable): SdnErrMsg { return if (e is SdnErrMsg) { e } else { SdnErrMsg.fromErrorCode(ExceptionHandle.handleException(e), getApp()) } } override fun handleError(results: Results<*>) { } fun handleSdnControllerError(errMsg: SdnErrMsg) { uiEvent.showDialog.postValue(Event(errMsg)) } /** * UI事件 * 使用以下三个默认Event来处理公共的事件。 */ inner class UIChange { val showDialog by lazy { MutableLiveData<Event<SdnErrMsg>>() } val loading by lazy { MutableLiveData<Event<Boolean>>() } val loadingExt by lazy { MutableLiveData<Event<Boolean>>() } val toastEvent by lazy { MutableLiveData<Event<String>>() } val autoDismissDialog by lazy {MutableLiveData<Event<String>>()} val showCustomDialog by lazy { MutableLiveData<Event<String>>() } } fun getApp(): Application { return OmadaApplication.getInstance() } fun getString(@StringRes id: Int): String { return OmadaApplication.getInstance().resources.getString(id) } fun getString(@StringRes id: Int, str: String): String { return OmadaApplication.getInstance().resources.getString(id, str) } fun getString(@StringRes id: Int, str1: String, str2: String): String { return OmadaApplication.getInstance().resources.getString(id, str1, str2) } fun getString(@StringRes id: Int, num: Int): String { return OmadaApplication.getInstance().resources.getString(id, num) } fun getString(@StringRes id: Int, num: Int, num1: Int): String { return OmadaApplication.getInstance().resources.getString(id, num, num1) } fun getColor(@ColorRes color: Int): Int { return OmadaApplication.getInstance().resources.getColor(color) } /** * @Method * @Description 点击设备列表 * @Date: 2021/4/16 16:53 * @Author: hxw * @Param * @Return */ fun onDeviceClick(manager: ControllerSessionManager, type: String, mac: String, successBlock: () -> Unit) { // 如果没有devices权限,直接提示no permission if (manager.getCurrentSdnSession()?.isMspRoleSiteDeviceManageBlock() == true) { uiEvent.toastEvent.postValue(Event(getString(R.string.role_no_permission))) } else { uiEvent.loadingExt.postValue(Event(true)) // 支持分页获取后直接请求 if (supportGetDeviceByPage) { searchDeviceByMac(manager, mac, { it?.let { checkDeviceStatus(manager, it, successBlock) } }, { showErrorMsg(type) }) } else { // device 组件协商 getDeviceFromCache(manager, mac, { checkDeviceStatus(manager, it, successBlock) }, { // cache 设备列表未找到设备,暂不做处理 showErrorMsg(type) }) } } } private fun showErrorMsg(deviceType: String) { uiEvent.loadingExt.postValue(Event(false)) when (DeviceType.fromString(deviceType)) { DeviceType.AP -> { uiEvent.toastEvent.postValue(Event(getString(R.string.sdn_server_error_ap_does_not_exist))) } DeviceType.GATEWAY -> { uiEvent.toastEvent.postValue(Event(getString(R.string.sdn_server_error_gateway_does_not_exist))) } DeviceType.SWITCH -> { uiEvent.toastEvent.postValue(Event(getString(R.string.sdn_server_error_switch_does_not_exist))) } DeviceType.OLT -> { uiEvent.toastEvent.postValue(Event(getString(R.string.olt_does_not_exist))) } else -> { uiEvent.toastEvent.postValue(Event(getString(R.string.sdn_server_error_device_not_exist))) } } } /** * 根据mac请求设备信息 */ private fun searchDeviceByMac(manager: ControllerSessionManager, mac: String, successBlock: (Device?) -> Unit, errorBlock: () -> Unit) { mspDeviceRepo = manager.createSdnRepository(MspDeviceRepository::class.java) val map = mapOf<String, String>( EnumQueryParameter.PAGE.value to "1", EnumQueryParameter.PAGE_SIZE.value to SdnDeviceListBaseViewModel.PAGE_SIZE.toString(), EnumQueryParameter.SEARCH_KEY.value to mac ) launchOnlyResult({ mspDeviceRepo.getDevice(map) }, { it.data?.find { device -> device.mac == mac }?.let { result -> successBlock(result) } ?: errorBlock.invoke() }, { errorBlock.invoke() }, { }, false) } /** * @Method * @Description 获取缓存中设备列表 * @Date: 2021/4/16 16:32 * @Author: hxw * @Param * @Return */ fun getDeviceFromCache(manager: ControllerSessionManager, mac: String, successBlock: (Device) -> Unit, errorBlock: () -> Unit) { val device = manager.getCurrentSdnSession()!!.getDeviceFromList(mac) if (device != null) { successBlock.invoke(device) } else { launchBackground({ val repository: DeviceRepository = manager.createSdnRepository(DeviceRepository::class.java) repository.getDevice() }, { val device = it.find { it.mac == mac } if (device != null) { successBlock.invoke(device) } else { errorBlock.invoke() } manager.getCurrentSdnSession()?.setDeviceList(it) }, { errorBlock.invoke() }) } } /** * @Method * @Description 检查设备的当前状态 * @Date: 2021/4/16 16:33 * @Author: hxw * @Param * @Return */ fun checkDeviceStatus(manager: ControllerSessionManager, device: Device, successBlock: () -> Unit) { if (device.active == false) { makeComponentsAndGotoDeviceDetail(manager, device.type, device.mac, successBlock) return } when (SdnDeviceStatus.fromCode(device.status)) { SdnDeviceStatus.PENDING, SdnDeviceStatus.PENDING_WIRELESS -> { uiEvent.loadingExt.postValue(Event(false)) uiEvent.toastEvent.postValue(Event(getString(R.string.device_error_pending))) } SdnDeviceStatus.MANAGED_BY_OTHERS, SdnDeviceStatus.MANAGED_BY_OTHERS_WIRELESS -> { uiEvent.loadingExt.postValue(Event(false)) uiEvent.toastEvent.postValue(Event(getString(R.string.device_error_manage_by_other))) } SdnDeviceStatus.ADOPT_FAILED, SdnDeviceStatus.ADOPT_FAILED_WIRELESS -> { uiEvent.loadingExt.postValue(Event(false)) uiEvent.toastEvent.postValue(Event(getString(R.string.device_error_adopt_failed))) } SdnDeviceStatus.ADOPTING, SdnDeviceStatus.ADOPTING_WIRELESS -> { uiEvent.loadingExt.postValue(Event(false)) uiEvent.toastEvent.postValue(Event(getString(R.string.device_error_adopting))) } SdnDeviceStatus.PROVISIONING -> { uiEvent.loadingExt.postValue(Event(false)) uiEvent.toastEvent.postValue(Event(getString(R.string.device_error_provisioning))) } SdnDeviceStatus.CONFIGURING -> { uiEvent.loadingExt.postValue(Event(false)) uiEvent.toastEvent.postValue(Event(getString(R.string.device_error_configuring))) } SdnDeviceStatus.UPGRADING -> { uiEvent.loadingExt.postValue(Event(false)) uiEvent.toastEvent.postValue(Event(getString(R.string.device_error_upgrading))) } SdnDeviceStatus.REBOOTING -> { uiEvent.loadingExt.postValue(Event(false)) uiEvent.toastEvent.postValue(Event(getString(R.string.device_error_rebooting))) } SdnDeviceStatus.DISCONNECTED, SdnDeviceStatus.DISCONNECTED_MIGRATING, SdnDeviceStatus.HEARTBEAT_MISSED, SdnDeviceStatus.HEARTBEAT_MISSED_MIGRATING, SdnDeviceStatus.HEARTBEAT_MISSED_WIRELESS, SdnDeviceStatus.HEARTBEAT_MISSED_WIRELESS_MIGRATING, SdnDeviceStatus.ISOLATED, SdnDeviceStatus.ISOLATED_MIGRATING, SdnDeviceStatus.CONNECTED, SdnDeviceStatus.CONNECTED_MIGRATING, SdnDeviceStatus.CONNECTED_WIRELESS, SdnDeviceStatus.CONNECTED_WIRELESS_MIGRATING -> { makeComponentsAndGotoDeviceDetail(manager, device.type, device.mac, successBlock) } else -> { uiEvent.loadingExt.postValue(Event(false)) // do nothing } } } /** * @Method * @Description 组件协商并且跳转设备详情 * @Date: 2021/4/16 16:23 * @Author: hxw * @Param * @Return */ fun makeComponentsAndGotoDeviceDetail(manager: ControllerSessionManager, type: String, mac: String, successBlock: () -> Unit) { if (manager.getCurrentSdnSession()!!.getDeviceComponents(mac) != null) { successBlock() uiEvent.loadingExt.postValue(Event(false)) } else { val repository: DeviceRepository = manager.createSdnRepository(DeviceRepository::class.java) val oltRepo: OltRepository by lazy { manager.createSdnV5Repository(OltRepository::class.java) } when (type) { "ap" -> { launchOnlyResult({ repository.getApComponente(mac) }, { manager.getCurrentSdnSession()?.apply { setDeviceComponents(mac, it) } successBlock() }, { }, { uiEvent.loadingExt.postValue(Event(false)) }, false) } "switch" -> { launchOnlyResult({ repository.getSwitchComponente(mac) }, { manager.getCurrentSdnSession()?.apply { setDeviceComponents(mac, it) } successBlock() }, { }, { uiEvent.loadingExt.postValue(Event(false)) }, false) } "gateway" -> { launchOnlyResult({ repository.getGatewayComponente(mac) }, { manager.getCurrentSdnSession()?.apply { setDeviceComponents(mac, it) } successBlock() }, { }, { uiEvent.loadingExt.postValue(Event(false)) }, false) } "olt" -> { launchOnlyResult({ oltRepo.getOltComponent(mac) }, { manager.getCurrentSdnSession()?.apply { setDeviceComponents(mac, it) } successBlock() }, { }, { uiEvent.loadingExt.postValue(Event(false)) }, false) } else -> { successBlock() uiEvent.loadingExt.postValue(Event(false)) } } } } /** * @Method * @Description 点击client列表 * @Date: 2021/4/16 16:53 * @Author: hxw * @Param * @Return */ fun onClientClick(manager: ControllerSessionManager, mac: String, successBlock: (Boolean) -> Unit) { // device 组件协商 getClientByMac(manager, mac, { successBlock.invoke(it.wireless) }, { // cache client 列表未找到设备,暂不做处理 uiEvent.toastEvent.postValue(Event(getString(R.string.sdn_server_error_client_not_exist))) }) } /** * @Method * @Description 获取缓存中client列表 * @Date: 2021/4/16 16:32 * @Author: hxw * @Param * @Return */ private fun getClientByMac(manager: ControllerSessionManager, mac: String, successBlock: (ClientInfo) -> Unit, errorBlock: () -> Unit) { searchClientByMac(manager, mac) { if (clientResult != null) { successBlock.invoke(clientResult!!) } else { errorBlock.invoke() } } } private fun searchClientByMac(manager: ControllerSessionManager, mac: String, successBlock: () -> Unit): ClientInfo? { repository = manager.createSdnRepository(ClientRepository::class.java) clientResult = null val map = mapOf<String, String>("currentPage" to "1", "currentPageSize" to SdnControllerSiteViewModel.PAGE_SIZE.toString(), "searchKey" to mac, "searchField" to "clientMac", "filters.active" to "true") launchOnlyResult({ repository.getClient(map) }, { for (client in it.data) { if (mac == client.mac) { clientResult = client } } successBlock() }) return clientResult } fun getLanguageCode(): Int { // 简体与繁体返回语言码都是“zh” if (LanguageType.fromString(Locale.getDefault().language) == LanguageType.CHINESE) { val languageTag = Locale.getDefault().toLanguageTag() return if (languageTag == "zh-Hant-TW" || languageTag == "zh-Hant-HK" || languageTag == "zh-Hant-MO" || languageTag == "zh-TW" || languageTag == "zh-HK" || languageTag == "zh-MO" ) { EnumLanguageCode.LANGUAGE_CODE_CHINESE.code } else { EnumLanguageCode.LANGUAGE_CODE_ENGLISH.code } } return when (LanguageType.fromString(Locale.getDefault().language)) { LanguageType.ENGLISH -> EnumLanguageCode.LANGUAGE_CODE_ENGLISH.code LanguageType.GERMAN -> EnumLanguageCode.LANGUAGE_CODE_GERMAN.code LanguageType.FRENCH -> EnumLanguageCode.LANGUAGE_CODE_FRENCH.code LanguageType.SPANISH -> EnumLanguageCode.LANGUAGE_CODE_SPANISH.code LanguageType.ITALIAN -> EnumLanguageCode.LANGUAGE_CODE_ITALIAN.code LanguageType.PORTUGUESE -> EnumLanguageCode.LANGUAGE_CODE_PORTUGUESE.code LanguageType.RUSSIAN -> EnumLanguageCode.LANGUAGE_CODE_RUSSIAN.code LanguageType.TURKISH -> EnumLanguageCode.LANGUAGE_CODE_TURKISH.code LanguageType.JAPANESE -> EnumLanguageCode.LANGUAGE_CODE_JAPANESE.code LanguageType.KOREAN -> EnumLanguageCode.LANGUAGE_CODE_KOREAN.code LanguageType.CZECH -> EnumLanguageCode.LANGUAGE_CODE_CZECH.code LanguageType.DUTCH -> EnumLanguageCode.LANGUAGE_CODE_DUTCH.code LanguageType.POLISH -> EnumLanguageCode.LANGUAGE_CODE_POLISH.code LanguageType.SLOVAKIAN -> EnumLanguageCode.LANGUAGE_CODE_SLOVAKIAN.code LanguageType.HUNGARIAN -> EnumLanguageCode.LANGUAGE_CODE_HUNGARIAN.code LanguageType.BULGARIAN -> EnumLanguageCode.LANGUAGE_CODE_BULGARIAN.code LanguageType.ROMANIAN -> EnumLanguageCode.LANGUAGE_CODE_ROMANIAN.code LanguageType.UKRAINIAN -> EnumLanguageCode.LANGUAGE_CODE_UKRAINIAN.code LanguageType.SERBIAN -> EnumLanguageCode.LANGUAGE_CODE_SERBIAN.code LanguageType.ARABIC -> EnumLanguageCode.LANGUAGE_CODE_ARABIC.code else -> EnumLanguageCode.LANGUAGE_CODE_UNKNOWN.code } } fun updateExtLoadingStatus(status: Boolean) { uiEvent.loadingExt.postValue(Event(status)) } }
09-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值