Android实现优雅快速的网络请求

Retrofit是如何支持协程 一、概述 Kotlin的协程很好用,相信大家都用上了,也觉得很香,这不,Retrofit在最近的几个版本中就支持协程了,更加方便我们处理网络请求了。这里不说协程的用法,我比较好奇Retrofit是怎么识别并处理我们写的suspend方法,下面就以retrofit:2.8.1的版本来看看究竟是如何实现的。 二、java眼中的suspend 在研究Retrofit代码之前,我们先看一个问题,kotlin完全兼容java,但suspend是kotlin中的,java中并没有,那这是怎么兼容的呢?为了看看究竟,我们 阅读详情

目标

  • 简单调用、少写重复代码

  • 不依赖第三方库(只含Retrofit+Okhttp+协程)

  • 完全不懂协程也能立马上手(模板代码)

用Kotlin的方式写Kotlin代码,什么意思呢?对比一下下面2个代码就知道了:

mViewModel.wxArticleLiveData.observe(this, object : IStateObserver<List<WxArticleBean>>() {

    override fun onSuccess(data: List<WxArticleBean>?) {
    }

    override fun onError() {
    }
})
mViewModel.wxArticleLiveData.observeState(this) {

    onSuccess { data: List<WxArticleBean>? ->
    }

    onError {
    }
}

既然是用Kotlin了,就不要用Java的方式写接口回掉了,DSL表达式不香么?

提供两种方式实现:

  • 方式一代码量更少,网络请求自带Loading,不需要手动调用Loading

  • 方式二解耦更彻底

两种方式设计思路在解耦这一块存在差异,看具体需求,没有谁好谁差,依照自己的项目,哪个更方便用哪个。

基于官方架构的封装:

一、封装一

核心思想是:通过一个LiveData 贯穿整个流程,借用网上一张图:

Activity中的代码示例

点击请求网络
mViewModel.getArticleData()

设置监听,只监听成功的结果,使用默认异常处理

mViewModel.wxArticleLiveData.observeState(this) {
    onSuccess { data ->
        Log.i("wutao","网络请求的结果是:$data")
    }
}

如果需要单独处理每一个回调

这些回调都是可选的,不需要可不实现

mViewModel.wxArticleLiveData.observeState(this) {
    onSuccess { data ->
        Log.i("wutao","网络请求的结果是:$data")
    }

    onEmpty{
        Log.i("wutao", "返回的数据是空,展示空布局")
    }

    onFailed {
        Log.i("wutao", "后台返回的errorCode: $it")
    }

    onException { e ->
        Log.i("wutao","这是非后台返回的异常回调")
    }

    onShowLoading {
         Log.i("wutao","自定义单个请求的Loading")
    }

    onComplete {
        Log.i("wutao","网络请求结束")
    }
}
请求自带Loading

很多网络请求都需要Loading,不想每次都写onShowLoading{}方法,也so easy。

mViewModel.wxArticleLoadingLiveData.observeState(this, this) {
    onSuccess { data ->
  Log.i("wutao","网络请求的结果是:$data")
    }
}

observeState()第二个方法传入ui的引用就可,这样单个网络请求之前会自动加载Loading,成功或者失败自动取消Loading。

上面代码都是Activity中,我们来看下ViewModel中。

ViewModel中代码示例

class MainViewModel{

    private val repository by lazy { WxArticleRepository() }

    val wxArticleLiveData = StateLiveData<List<WxArticleBean>>()

    fun requestNet() {
        viewModelScope.launch {
            repository.fetchWxArticle(wxArticleLiveData)
        }
    }
}

很简单,引入对应的数据仓库Repo,然后使用协程执行网络请求方法。来看下Repo中的代码。

Repository中代码示例

class WxArticleRepository : BaseRepository() {

    private val mService by lazy { RetrofitClient.service }

    suspend fun fetchWxArticle(stateLiveData: StateLiveData<List<WxArticleBean>>) {
        executeResp(stateLiveData, mService::getWxArticle)
    }  
}
interface ApiService {

    @GET("wxarticle/chapters/json")
    suspend fun getWxArticle(): BaseResponse<List<WxArticleBean>>
}

获取一个Retrofit实例,然后调用ApiService接口方法。

封装一的优势

  • 代码很简洁,不需要手写线程切换代码,没有很多的接口回调。

  • 自带Loading状态,不需要手动启用Loading和关闭Loading。

  • 数据驱动ui,以LiveData为载体,将页面状态和网络结果通过在LiveData返回给ui。

项目地址见:

https://github.com/ldlywt/FastJetpack/tree/withLoading  (分支名字是:withLoading)

封装一的不足

*封装一的核心思想是:一个LiveData贯穿整个网络请求链。这是它的优势,也是它的劣势。

  • 解耦不彻底,违背了"在应用的各个模块之间设定明确定义的职责界限"的思想

  • LiveData监听时,如果需要Loading,BaseActivity都需要实现带有Loading方法接口。

  • obserState()方法第二个参数中传入了UI引用。

  • 不能达到"看方法如其意",如果是刚接触,会有很多疑问:为什么需要一个livedata作为方法的参数。网络请求的返回值去哪了?

  • 封装一还有一个最大的缺陷:对于是多数据源,封装一就展示了很不友好的一面。

Repository是做一个数据仓库,项目中获取数据的方式都在这里同意管理,网络获取数据只是其中一个方式而已。

如果想加一个从数据库或者缓存中获取数据,封装一想改都不好改,如果强制改就破坏了封装,侵入性很大。

针对封装一的不足,优化出了封装二。

二、封装二

思路
  • 想要解决上面的不足,不能以LiveData为载体贯穿整个网络请求。

  • Observe()方法中去掉ui引用,不要小看一个ui引用,这个引用代表着具体的Activity跟Observe耦合起来了,并且Activity还要实现IUiView接口。

  • 网络请求跟Loading状态分开了,需要手动控制Loading。

  • Repository中的方法都有返回值,会返回结果,也不需要用livedata作为方法参数。

  • LiveData只存在于ViewModel中,LiveData不会贯穿整个请求链。Repository中也不需要LiveData的引用,Repository的代码就是单纯的获取数据。

  • 针对多数据源,也非常好处理。

  • 跟ui没任何关系,可以完全作为一个独立的Lib使用。

Activity中代码

// 请求网络
mViewModel.login("username", "password")

// 注册监听
mViewModel.userLiveData.observeState(this) {
    onSuccess {data ->
        mBinding.tvContent.text = data.toString()
    }

    onComplete {
        dismissLoading()
    }
}

observeState()中不再需要一个ui引用了。

ViewModel中

class MainViewModel {

    val userLiveData = StateLiveData<User?>()

    fun login(username: String, password: String) {
        viewModelScope.launch {
            userLiveData.value = repository.login(username, password)
        }
    }
}

通过livedata的setValue或者postValue方法将数据发送出去。

Repository中

suspend fun login(username: String, password: String): ApiResponse<User?> {
    return executeHttp {
        mService.login(username, password)
    }
}

Repository中的方法都返回请求结果,并且方法参数不需要livedata。Repository完全可以独立出来了。

针对多数据源
// WxArticleRepository
class WxArticleRepository : BaseRepository() {

    private val mService by lazy {
        RetrofitClient.service
    }

    suspend fun fetchWxArticleFromNet(): ApiResponse<List<WxArticleBean>> {
        return executeHttp {
            mService.getWxArticle()
        }
    }

    suspend fun fetchWxArticleFromDb(): ApiResponse<List<WxArticleBean>> {
        return getWxArticleFromDatabase()
    }
}
// MainViewModel.kt  
private val dbLiveData = StateLiveData<List<WxArticleBean>>()
private val apiLiveData = StateLiveData<List<WxArticleBean>>()
val mediatorLiveDataLiveData = MediatorLiveData<ApiResponse<List<WxArticleBean>>>().apply {
    this.addSource(apiLiveData) {
        this.value = it
    }
    this.addSource(dbLiveData) {
        this.value = it
    }
}

可以看到,封装二更符合职责单一原则,Repository单纯的获取数据,ViewModel对数据进行处理和发送。

三、实现原理

数据来源于鸿洋大神的玩Android 开放API

回数据结构定义:

{
    "data": ...,
    "errorCode": 0,
    "errorMsg": ""
}

封装一和封装二的代码差距很小,主要看封装二。

定义数据返回类

open class ApiResponse<T>(
        open val data: T? = null,
        open val errorCode: Int? = null,
        open val errorMsg: String? = null,
        open val error: Throwable? = null,
) : Serializable {
    val isSuccess: Boolean
        get() = errorCode == 0
}

data class ApiSuccessResponse<T>(val response: T) : ApiResponse<T>(data = response)

class ApiEmptyResponse<T> : ApiResponse<T>()

data class ApiFailedResponse<T>(override val errorCode: Int?, override val errorMsg: String?) : ApiResponse<T>(errorCode = errorCode, errorMsg = errorMsg)

data class ApiErrorResponse<T>(val throwable: Throwable) : ApiResponse<T>(error = throwable)

基于后台返回的基类,根据不同的结果,定义不同的状态数据类。

网络请求统一处理:BaseRepository

open class BaseRepository {

    suspend fun <T> executeHttp(block: suspend () -> ApiResponse<T>): ApiResponse<T> {
        runCatching {
            block.invoke()
        }.onSuccess { data: ApiResponse<T> ->
            return handleHttpOk(data)
        }.onFailure { e ->
            return handleHttpError(e)
        }
        return ApiEmptyResponse()
    }

    /**
     * 非后台返回错误,捕获到的异常
     */
    private fun <T> handleHttpError(e: Throwable): ApiErrorResponse<T> {
        if (BuildConfig.DEBUG) e.printStackTrace()
        handlingExceptions(e)
        return ApiErrorResponse(e)
    }

    /**
     * 返回200,但是还要判断isSuccess
     */
    private fun <T> handleHttpOk(data: ApiResponse<T>): ApiResponse<T> {
        return if (data.isSuccess) {
            getHttpSuccessResponse(data)
        } else {
            handlingApiExceptions(data.errorCode, data.errorMsg)
            ApiFailedResponse(data.errorCode, data.errorMsg)
        }
    }

    /**
     * 成功和数据为空的处理
     */
    private fun <T> getHttpSuccessResponse(response: ApiResponse<T>): ApiResponse<T> {
        return if (response.data == null || response.data is List<*> && (response.data as List<*>).isEmpty()) {
            ApiEmptyResponse()
        } else {
            ApiSuccessResponse(response.data!!)
        }
    }

}

Retrofit协程的错误码处理是通过异常抛出来的,所以通过try…catch来捕捉非200的错误码。包装成不同的数据类对象返回。

扩展LiveData和Observer

在LiveData的Observer()来判断是哪种数据类,进行相应的回调处理:

abstract class IStateObserver<T> : Observer<ApiResponse<T>> {

    override fun onChanged(apiResponse: ApiResponse<T>) {
        when (apiResponse) {
            is ApiSuccessResponse -> onSuccess(apiResponse.response)
            is ApiEmptyResponse -> onDataEmpty()
            is ApiFailedResponse -> onFailed(apiResponse.errorCode, apiResponse.errorMsg)
            is ApiErrorResponse -> onError(apiResponse.throwable)
        }
        onComplete()
    }

再扩展LiveData,通过kotlin的DSL表达式替换java的callback回调,简写代码。

class StateLiveData<T> : MutableLiveData<ApiResponse<T>>() {

    fun observeState(owner: LifecycleOwner, listenerBuilder: ListenerBuilder.() -> Unit) {
        val listener = ListenerBuilder().also(listenerBuilder)
        val value = object : IStateObserver<T>() {

            override fun onSuccess(data: T) {
                listener.mSuccessListenerAction?.invoke(data)
            }

            override fun onError(e: Throwable) {
                listener.mErrorListenerAction?.invoke(e) ?: toast("Http Error")
            }

            override fun onDataEmpty() {
                listener.mEmptyListenerAction?.invoke()
            }

            override fun onComplete() {
                listener.mCompleteListenerAction?.invoke()
            }

            override fun onFailed(errorCode: Int?, errorMsg: String?) {
                listener.mFailedListenerAction?.invoke(errorCode, errorMsg)
            }

        }
        super.observe(owner, value)
    }
}

四、总结

封装一:代码量更少,可以根据项目需要封装一些具体的ui相关,开发起来更快速,用起来更爽。

封装二:解耦更彻底,可以独立于ui模块运行。

个人认为,框架设计主要还是服务于自己的项目需求(开源项目除外),符合设计模式和设计原则更好,但是不满足也没关系,适合自己项目需求,能节省自己的时间,就是好的。

我们自己项目中使用,怎么轻便,怎么快速,怎么写的爽就怎么来。

原文链接:https://juejin.cn/post/6993294489125126151

文末

您的点赞收藏就是对我最大的鼓励!
欢迎关注我,分享Android干货,交流Android技术。
对文章有何见解,或者有何技术问题,欢迎在评论区一起留言讨论!

Retrofit+协程使用填坑和优化 本文章主要记录在项目中使用Retrofit+协程时遇到的问题,当然有关问题不局限于使用协程,可能使用RxJava或者原始Call也会遇到,所以算是对Retrofit相关问题的解决和优化。文章第一个问题讲的比较啰嗦,主要介绍了当我们遇到问题时应该怎样去分析,并学会使用相关工具定位问题产生的根本原因,这样才能更好的解决问题,而后面的就直接简单的描述问题、阐述原因和解决办法。 1. (优化)Retrofit+协程第一次请求时卡顿现象 1.1 背景 /**1. 接口定义*/ @POST("jeecg-boot/.. 阅读详情

相关推荐

【Jetpack篇】协程+Retrofit网络请求状态封装实战(2)

为数据请求的公共方法,该方法传入了两个参数,第一个是将数据请求函数当作参数,第二个就是上面新建的。方法一开始就新建了一个BaseResp()对象,将状态设置给BaseResp的dataState,接着开始对数据请求进行异常处理(具体可查看),如果code=0表示接口请求成功,否则表示接口请求成功,服务器返回错误。在code=0时,对返回数据进行判空处理,因为数据有多种类型,这里需要自己设置类型进行判断,为空就将状态设置为,否则为。如果抛出异常,则将状态设置为,在请求结束后,利用。

2401_84123171的博客 1055

两种方式封装Retrofit+协程,实现优雅快速的网络请求

目的 简单调用、少写重复代码 不依赖第三方库(只含Retrofit+Okhttp+协程) 完全不懂协程也能立马上手(模板代码) 用Kotlin的方式写Kotlin代码,什么意思呢?对比一下下面2个代码就知道了: mViewModel.wxArticleLiveData.observe(this, object : IStateObserver<List<WxArticleBean>>() { override fun onSucc.

A_pyf的博客 932

MVI 架构封装:快速优雅地实现网络请求

前言 网络请求可以说是Android开发中最常见的需求之一,基本上每个页面都需要发起几个网络请求。 因此大家通常都会对网络请求进行一定的封装,解决模板代码过多,重复代码,异常捕获等一些问题 前面我们介绍了MVI架构的主要原理与更佳实践 MVVM 进阶版:MVI 架构了解一下~ MVI 架构更佳实践:支持 LiveData 属性监听 我们这次一起来看下MVI架构下如何对网络请求进行封装,以及相对于MVVM架构有什么优势 本文主要包括以下内容 MVVM架构下的网络请求封装与问题 MVI架构下封装网络请求 MV

BUG修复ing 309

Android 协程与retrofit库的结合使用

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、retrofit2.6.0之前使用步骤1.引入库2.创建接收服务器返回数据的类(根据具体数据对应)3.定义描述网络请求的接口4.创建retrofit实例及接口实例创建函数5.发送网络请求6.调用封装为LiveData()数据二、retrofit2.6.0之后使用步骤1.导入依赖2.创建接收服务器返回数据的类(根据具体数据对应)3.定义描述网络请求的接口4.创建retrofit实例5.创建协程调用函数三、scope协程作用域使

qq_45901004的博客 3554

AI开发提效10倍:从需求到部署的全流程实战指南(附Prompt模板)

用AI开发不是“偷懒”,而是把时间花在更有价值的地方——原来花80%时间写重复代码,现在用AI搞定后,能把精力放在“优化用户体验”“提升系统性能”这些核心工作上,这才是AI给开发者的真正红利。如果你还没开始用AI做开发,建议从“写一个简单接口”“补一段注释”开始尝试,先用起来再优化方法。记住:AI是工具,不是对手,学会驾驭它,你会发现开发效率提升的同时,还能告别无效加班。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1533

1.47寸ST7789V3彩色TFT LCD嵌入式驱动详解

TFT LCD是嵌入式人机交互(HMI)的核心显示技术,其工作原理依赖于行列驱动、RGB像素寻址与伽马校正等模拟/数字协同机制。ST7789V3作为主流低功耗TFT控制器,支持SPI接口与16位RGB565数据格式,具备高兼容性与轻量级驱动优势。在资源受限的MCU平台(如ARM Cortex-M系列)上,结合RT-Thread设备驱动模型与QSPI硬件加速,可实现高效显存管理、Bresenham图形算法及GB2312中文字模渲染。典型应用场景涵盖便携设备状态屏、工业HMI面板与教育开发套件——本文以1.47

weixin_42599908的博客 125

2024年安卓最新Android实现优雅快速的网络请求,2024年最新软件开发项目经理面试题库

给大家分享一份移动架构大纲,包含了移动架构师需要掌握的所有的技术体系,大家可以对比一下自己不足或者欠缺的地方有方向的去学习提升;网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。需要这份系统化学习资料的朋友,可以戳这里获取一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!/**

FZBH_Q的博客 998

5分钟搞懂MSDNet:用Transformer实现小样本语义分割的保姆级教程

本文详细介绍了MSDNet(Multi-Scale Decoder Network)如何利用Transformer架构实现小样本语义分割。通过多尺度解码器和空间Transformer解码器,MSDNet能够在仅有1-5张标注图像的情况下完成精确分割任务。文章提供了PyTorch代码实例和优化技巧,帮助开发者快速掌握这一前沿技术。

weixin_30832143的博客 506

2024年Android实现优雅快速的网络请求(1),音视频面试题及答案

在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。

2401_84538135的博客 702

LaMAR数据集下载和使用流程

LaMAR数据集

qq_51745206的博客 976

AHRS互补滤波(Mahony)算法及开源代码

AHRS(Attitude and heading ref AHRS(Attitude and heading reference system,也就是航姿参考系统。在互补滤波算法中传感器主要采用了IMU(陀螺仪、加速度计)和磁力计。 AHRS的基本思想是,在载体没有平移运动的情况下,通过加速度感知重力分量,可以计算出载体的俯仰(Pitch)和横滚(Pitch);磁力计可以感知磁北方向,因此可以计算载体的磁北航向;而陀螺仪测量输出载体的旋转角速度,通过积分可以计算得到横滚、俯仰、航向增量,但由于陀螺输出值含

weixin_42918498的博客 3万+

两种方式封装Retrofit+协程,实现优雅快速的网络请求,逆袭面经分享

override fun onSuccess(data: List?) { } override fun onError() { } }) mViewModel.wxArticleLiveData.observeState(this) { onSuccess { data: List? -> } onError { } } 既然是用Kotlin了,就不要用Java的方式写接口回掉了,DSL表达式不香么? 提供两种方式实现: 方式一代码量更少,网络请求自带Loading,不需要手动调用Loading

m0_64604893的博客 594

OpenIddict实战指南:在.NET Core中构建安全的OAuth 2.0与OpenID Connect服务

本文详细介绍了如何在.NET Core中使用OpenIddict框架构建安全、标准的OAuth 2.0与OpenID Connect授权服务。内容涵盖从快速搭建授权服务器、理解核心配置与授权流程,到集成用户数据库、实现完整登录授权,以及生产环境下的安全加固与部署指南,为.NET开发者提供了一套现代、可维护的认证授权解决方案。

weixin_29229989的博客 355

Android working with Volley Library

Volley提供了优美的框架,使得Android应用程序网络访问更容易和更快。Volley抽象实现了底层的HTTP Client库,让你不关注HTTP Client细节,专注于写出更加漂亮、干净的RESTful HTTP请求。另外,Volley请求会异步执行,不阻挡主线程。 Volley提供的功能 简单的讲,提供了如下主要的功能: 1、封装了的异步的RESTful 请求API;

Kevin Studio 385

Matlab之App Designer 一键自动生成带有表格的报告

本文采用案例讲解的方式介绍了采用Matlab中的App Designer开发可视化GUI分析界面后,实现一键自动导出带有表格报告的方法和步骤。可以实现从报告编制等繁琐的工作中解脱出来。

m0_59012156的博客 356

【麒麟系统】Rsync文件复制与同步工具

本文摘要: Rsync是一款Linux/Unix系统标配的高效文件同步工具,支持增量传输、SSH加密、断点续传等核心功能,相比SCP具有显著优势。文章详细解析了Rsync的五种标准语法格式和常用参数组合,重点介绍了本地同步、远程SSH同步(推送/拉取)的实操方法,并提供了密钥免密登录配置方案。针对企业运维场景,还讲解了文件过滤、镜像同步(--delete)、迁移同步(--remove-source-files)、空运行预校验(--dry-run)等高级功能,以及带宽限速等优化技巧,帮助用户安全高效地完成各类

信创运维工程师 · 银河麒麟 & 容器实战 | 金融生产环境迁移·等保加固 | 142篇原创·17万+阅读 999

java extends staric_GitHub - Yu113/KUtils-master: 封装android开发中常用的Utils,也许你的项目只需要这一个库就完全够了。不信你看,有图有真相...

README封装android开发中常用的Utils,也许你的项目只需要这一个库就完全够了。不信你看,有图有真相。集成优雅的日志打印风格、app引导页面两行代码实现(也可用作轮播广告图,支持加载本地和网络,一键开启自动翻页功能,内设好几种翻页动画)、高仿iOS进度条和对话框、activity基类的封装(可继承自BaseActivity自行拓展)、常用自定义View(圆角头像等)、Glide一行代码...

weixin_34972980的博客 302

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

RxjavaRetrofitDemo完全指南:如何优雅实现Android网络请求架构

在Android开发中,网络请求是每个应用都绕不开的核心功能。面对复杂的网络交互、异步处理和错误处理,如何构建一个优雅、可维护的网络请求架构成为开发者必须掌握的技能。**RxjavaRetrofitDemo**项目正是为了解决这个问题而生,它展示了如何将Retrofit与RxJava完美结合,打造出简洁高效的Android网络请求解决方案。 ## 🚀 为什么选择RxJava + Retrofi

gitblog_00916的博客 888

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

【Android】kotlin+协程+retrofit+mvvm 优雅地实现并封装网络请求

网络请求是软件开发中必不可少的一个部分,通过客户端向服务器发送请求,获取服务器上的资源,这些资源可以是网页内容、数据、文件等。通常遵循HTTP或其他协议,http是超文本传输协议,被用于在web浏览器和网站服务器之间传递信息,基于TCP/IP通信协议。根据不同的需求和场景,网络请求可以采用不同的方法,如GET、POST、PUT、DELETE等。一个完整的网络请求分为三个部分:请求行、请求头、请求体。

full courage的博客 3796

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

RetrofitClient:优雅地实现Android网络请求

RetrofitClient:优雅地实现Android网络请求 在Android开发中,处理网络请求是一项必不可少的任务,而RetrofitClient则是为此任务提供便利的一个强大工具。它基于Retrofit库,由GitHub用户NeglectedByBoss精心打造,旨在简化API接口的调用和管理。让我们一起深入了解RetrofitClient,并探讨它的核心特性、使用场景及优势。 项目简介 ...

gitblog_00093的博客 842

终极Android网络请求指南:如何用EasyHttp框架快速实现高效网络交互

EasyHttp是一款专为Android开发者打造的高效网络请求框架,以"简单易用,so easy"为设计理念,帮助开发者轻松处理各种网络请求场景。无论是基础的数据获取、文件上传下载,还是复杂的多域名配置、请求生命周期管理,EasyHttp都能提供简洁优雅的解决方案,让网络编程变得前所未有的简单。 [![Android网络请求框架背景图](https://raw.gitcode.com/gh_m

gitblog_00901的博客 340
上一篇: 今日份分享:Flutter自定义之旋转木马
下一篇: Android 实现抖音传送带特效
不秃头de程序猿
博客等级 码龄5年 4090粉丝 1478原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值