小小需求大大思考

需求:注册后首页弹出 toast

 

问题总结

问题1:OPPO手机默认关闭  设置===通知与状态栏===通知管理===APP名称打开通知

问题2:怎么加入接口不熟悉 activity/fragment

问题3:在不熟悉逻辑的情况下,在什么地方加入逻辑

问题4:Kotlin 、dagge 不够熟悉

问题5:前期准备不充分,浪费了很多时间,不明确时间节点

 

尝试过的错误方法

错误方法1:HomeFragment 处理逻辑;问题:如果从界面Fragment到注册界面回来,没弹出

错误方法2:登录过后,方法拦截;  问题:如果输入账号,验证码后就会弹出Toast

 

正确的方法(◔ ‸◔? (⊙.⊙)):

依次往下调用

SetPasswordActivity
SetPasswordViewModel
SetPasswordPresenter
AccountDataService---AccountDataManagerImpl

对比代码(无用)

data class ToastModel(
    val content: String?,
    val type: String?
)

 结构

 

SetPasswordActivity.kt

@Route(path = ARouters.Account.SET_PASSWORD)
class SetPasswordActivity : InjectedActivity(R.layout.activity_set_password) {

    @Inject
    lateinit var viewModel: SetPasswordViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initView()
    }

    private fun initView() { 
        // 提交按钮
        btn_submit.clickThrottle {
            viewModel.setPassword(ket_password.text.toString(), ket_invite_code?.text?.toString())
        }
    
    }
}
@Keep
data class ToastEntity(
    @SerializedName("content")
    var content: String? = null,
    @SerializedName("type")
    var type: String? = null
):Parcelable{
    constructor(parcel: Parcel) : this(
        parcel.readString(),
        parcel.readString()
    )

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeString(content)
        parcel.writeString(type)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<ToastEntity> {
        override fun createFromParcel(parcel: Parcel): ToastEntity {
            return ToastEntity(parcel)
        }

        override fun newArray(size: Int): Array<ToastEntity?> {
            return arrayOfNulls(size)
        }
    }
}
SetPasswordViewModel.kt

fun setPassword(password: String, inviteCode: String?) = launch {
            。。。
            .onSuccess {
               
                accountDataService?.getToastContent()
             
            }
            。。。
}
AuthService.kt

interface AuthService {
    /**
     * 获取toast 列表
     */
    @GET("/message/toast/list/")
    suspend fun getTokenStatus():  Response.List<ToastEntity>

}
AccountDataManagerImpl.kt

@Suppress("SENSELESS_COMPARISON", "USELESS_IS_CHECK")
@Route(path = ARouters.Account.ACCOUNT_DATA_SERVICE, name = "账户数据服务")
class AccountDataManagerImpl : AccountDataManager, AccountDataService,
    BaseDataServiceImpl<AuthService>() {

     override fun getToastContent() {
        safetyLaunch {
            delay(2000)
            safeApiCall {
                service.getTokenStatus()
            }.onSuccess {
                if (it?.list.isNullOrEmpty()) {
                    return@onSuccess
                }
                info(it?.list?.get(0)?.content)
            }.onFailure {
                it.handle()
            }
        }
    }
}
AccountDataService.kt.api

interface AccountDataService : IProvider {
    /**
     * 获取toast 列表
     */
    fun getToastContent()
}

关键代码详细解释

Coroutine 是轻量级的线程

使用 Coroutine 必须要先创建一个对应的 CoroutineScope

一般而言,在应用中具有生命周期的组件应该实现 CoroutineScope 接口,并负责该组件内 Coroutine 的创建和管理

为了方便创建 Coroutine,在 CoroutineScope 上有很多扩展函数,比如 launch、async、actor、cancel 等

GlobalScope 是 CoroutineScope 的一个单例实现

Job 代表 launch 创建的一个 Coroutine 实例即可,通过这个 job 对象可以控制这个 Coroutine 实例,比如调用 cancel 函数可以取消执行

suspend 修饰符,它可以告诉编译器,该函数需要在协程中执行

 

 

 

 

 /**
     * 安全启动.
     * @param block suspend CoroutineScope.() -> Unit
     * @return JobWrapper
     */
    fun safetyLaunch(block: suspend CoroutineScope.() -> Unit): JobWrapper {
        val jobWrapper = JobWrapper()
        jobWrapper.job = GlobalScope.launch(CoroutinesDispatchers.ui + rootJob) {
            runCatching {
                block.invoke(this)
            }.onFailure {
                jobWrapper.onFailure?.invoke(it) ?: Logger.e(it, "safetyLaunch")
            }
        }
        return jobWrapper
    }

 延迟2s

   delay(2000)

 异常捕获

/**
 * 封装api请求,并进行异常捕捉处理.
 * @param call suspend () -> Response<T>
 * @return Result<T>
 */
suspend fun <T : Any> safeApiCall(call: suspend () -> Response<T>): Result<T> =
    try {
        Result.Success(call.invoke().unwrap())
    } catch (e: Throwable) {
        Result.Error(e)
    }

  list为空判断


 if (it?.list.isNullOrEmpty()) {
                    return@onSuccess
                }
                info(it?.list?.get(0)?.content)
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
小小调度器是一种基于Arduino的简易调度器。Arduino是一款开源硬件平台,具有易用性和可编程性。小小调度器的主要功能是控制和协调多个任务的执行顺序和时间,以实现对系统资源的合理利用。 小小调度器通过调用Arduino的定时器功能和中断控制,可以实现多个任务的并发执行。它可以根据每个任务的优先级和时间要求,在合适的时刻切换任务的执行,以保证每个任务都按照预定的顺序和时间片进行处理。 小小调度器通常采用优先级调度算法,根据任务的重要程度和需求,将任务分为不同的优先级,并按照优先级顺序进行调度。它还可以根据任务状态的改变,实时地调整任务的执行顺序和时间。 小小调度器的设计需要考虑系统资源的限制和任务之间的相互影响。在编程时,需要合理分配处理器时间和内存空间,以及避免任务之间的冲突和资源竞争。同时,还需通过合适的调度策略,减少任务切换的开销,提高系统的响应速度和效率。 小小调度器在嵌入式系统和物联网应用中具有重要作用。它可以用于控制和管理传感器数据采集、通信模块的数据传输、外设的控制等任务。通过合理调度和管理这些任务,可以实现系统的功能拓展和性能优化。 总而言之,小小调度器利用Arduino的可编程性和灵活性,可以实现对多任务系统的任务调度和管理。它在嵌入式系统和物联网应用中具有广泛的应用前景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黄毛火烧雪下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值