个人技术总结——基于Android的Retrofit应用

222200113杨清坤 2024-12-11 22:03:12
这个作业属于哪个课程2401_CS_SE_FZU
这个作业要求在哪里软件工程实践总结&个人技术博客
这个作业的目标本学期软件工程实践以及个人掌握的技术的总结
其他参考文献探索Android Studio , Square Retrofit官方文档

目录

  • 一.技术概述
  • 1.1 Retrofit
  • 二.技术详述
  • 2.1 环境准备
  • 2.2 创建API服务接口
  • 2.3 3. 构建Retrofit实例
  • 2.4 执行网络请求
  • 2.5 处理响应数据
  • 2.6 错误处理
  • 2.6.1 onResponse 方法中的错误处理
  • 2.6.2 onFailure 方法中的错误处理
  • 三.技术使用中遇到的问题和解决过程
  • 3.1 问题一:认证令牌无效或缺失
  • 3.2 问题二:网络请求超时
  • 3.3 问题三 :处理不同的HTTP状态码
  • 四.总结
  • 五.参考文献

一.技术概述

1.1 Retrofit

  • Retrofit 是一个类型安全的HTTP客户端库,适用于Android和Java应用程序,用于简化RESTful API调用。它通过定义接口来描述HTTP请求,并自动将JSON响应转换为Kotlin数据类。
  • 学习Retrofit的原因在于其简化网络通信代码、提高开发效率以及支持协程(coroutines)等现代Kotlin特性。
  • 难点包括配置适配器和服务、处理复杂的JSON结构以及理解异步编程模型。

二.技术详述

2.1 环境准备

在build.gradle.kts文件中添加Retrofit依赖:

dependencies {
     implementation("com.squareup.retrofit2:retrofit:2.9.0")
    implementation("com.squareup.retrofit2:converter-gson:2.9.0")
    implementation("com.squareup.okhttp3:okhttp:4.9.0")
}

2.2 创建API服务接口

我们定义了ArticleApiService接口,用于与文章相关的RESTful API交互。该接口包含获取、删除、更新、添加文章及其图片的方法,使用Call来进行异步调用:

interface ArticleApiService {
    // 获取所有文章
    @GET("article/getAllArticle")
    fun getAllArticles(): Call<ArticleResponse>

    // 删除文章
    @DELETE("article/{id}/deleteArticle")
    fun deleteArticle(@Path("id") articleId: Int): Call<DeleteArticleResponse>

    // 根据分类获取文章列表
    @GET("article/getArticlesByClass")
    fun getArticleList(@Query("articleClass") data: String): Call<ArticleResponse>

    // 修改文章
    @PUT("article/{id}/updateArticle")
    fun updateArticle(
        @Path("id") id: Int,
        @Body articleUpdateRequest: ArticleUpdateRequest
    ): Call<UpdateArticleResponse>

    // 添加文章
    @POST("article/addArticle")
    fun addArticle(@Body article: ArticleRequest): Call<PostArticleResponse>

    // 为文章添加媒体文件(图片)
    @Multipart
    @POST("article/{id}/addPicture")
    fun addPicture(
        @Path("id") articleId: Int,
        @Part filePart: MultipartBody.Part
    ): Call<PostArticlePictureResponse>

    // 删除图片
    @DELETE("article/deletePicture")
    fun deletePicture(@Query("url") url: String): Call<PostArticlePictureResponse>

    // 获取文章的所有图片
    @GET("/article/{id}/getPictures")
    fun getArticlePictures(@Path("id") articleId: Int): Call<GetPicturesResponse>

    // 添加浏览历史
    @POST("/article/{id}/addHistory")
    fun addHistory(@Path("id") articleId: Int): Call<PostArticleHistory>
}

2.3 3. 构建Retrofit实例

过程包括设置Base URL、配置Gson转换器、集成OkHttp客户端以增强功能(如超时设置和添加请求头),并确保所有网络请求都携带有效的认证令牌。

// 获取用户认证令牌
val token: String = TokenManager.getToken(App.INSTANCE) ?: ""

// 创建 Retrofit 实例
val retrofit = Retrofit.Builder()
    .baseUrl("http://113.44.68.6:8080/") // 使用实际的基地址
    .addConverterFactory(GsonConverterFactory.create()) // 使用 Gson 作为 JSON 转换器
    .client(
        OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS) // 设置连接超时时间
            .writeTimeout(30, TimeUnit.SECONDS)   // 设置写入超时时间
            .readTimeout(30, TimeUnit.SECONDS)    // 设置读取超时时间
            .addInterceptor { chain ->
                val request = chain.request().newBuilder()
                    .addHeader("Authorization", "Bearer $token") // 在请求中添加 Authorization 头
                    .build()
                chain.proceed(request)
            }
            .build()
    )
    .build()

// 创建 API 服务接口的实例
val articleApiService = retrofit.create(ArticleApiService::class.java)

2.4 执行网络请求

使用Retrofit的enqueue方法发起异步请求,并通过回调处理成功和失败的情况

fun fetchArticles(callback: (List<Article>) -> Unit, onError: (String) -> Unit) {
    articleApi.getAllArticles().enqueue(object : Callback<ArticleResponse> {
        override fun onResponse(
            call: Call<ArticleResponse>,
            response: Response<ArticleResponse>
        ) {
            if (response.isSuccessful && response.body() != null) {
                callback(response.body()!!.data) // 将数据通过回调返回
            } else {
                onError("Error: ${response.message()}")
            }
        }

        override fun onFailure(call: Call<ArticleResponse>, t: Throwable) {
            onError("Network Error: ${t.message}")
        }
    })
}

2.5 处理响应数据

使用Gson转换器工厂自动解析JSON响应为Kotlin数据类。确保数据类是可序列化的

data class ArticleRequest(
    val userId: Int,
    val title: String,
    val content: String,
    val datetime: String,
    val articleClass: String
)

2.6 错误处理

2.6.1 onResponse 方法中的错误处理

override fun onResponse(
    call: Call<ArticleResponse>,
    response: Response<ArticleResponse>
) {
    if (response.isSuccessful && response.body() != null) {
        callback(response.body()!!.data) // 将数据通过回调返回
    } else {
        onError("Error: ${response.message()}") // 处理HTTP请求失败的情况
    }
}

2.6.2 onFailure 方法中的错误处理

override fun onFailure(call: Call<ArticleResponse>, t: Throwable) {
    onError("Network Error: ${t.message}") // 处理网络异常
}

三.技术使用中遇到的问题和解决过程

3.1 问题一:认证令牌无效或缺失

  • 描述:当尝试访问受保护的API端点时,服务器返回401 Unauthorized响应。
  • 解决方案
    1. 检查TokenManager.getToken(App.INSTANCE)是否正确获取了有效的认证令牌。
    2. 确保在每个请求中正确添加了Authorization头部,格式为Bearer 。
    3. 如果令牌过期,实现刷新机制,自动重新获取新的令牌并重试请求。
    示例:
.addInterceptor { chain ->
    val request = chain.request().newBuilder()
        .addHeader("Authorization", "Bearer $token")
        .build()
    if (token.isEmpty()) {
        // 可选:提示用户登录或刷新令牌
    }
    chain.proceed(request)
}

3.2 问题二:网络请求超时

  • 描述: 在网络状况不佳的情况下,API请求经常超时。
  • 解决方案:
    1. 调整OkHttp的连接、读取和写入超时设置,确保它们适合您的应用场景。

2. 实现重试机制,在首次请求失败后自动重试几次。
示例:

OkHttpClient.Builder()
    .connectTimeout(30, TimeUnit.SECONDS)
    .readTimeout(60, TimeUnit.SECONDS) // 增加读取超时时间
    .writeTimeout(30, TimeUnit.SECONDS)
    .retryOnConnectionFailure(true)
    .build()

3.3 问题三 :处理不同的HTTP状态码

  • 描述: 需要根据不同类型的HTTP状态码提供不同的用户反馈。
  • 解决方案:

1. 在onResponse回调中检查具体的HTTP状态码,并根据情况显示适当的错误信息。
2. 提供更友好的用户反馈,例如提示用户检查网络连接或重新登录。
示例:

override fun onResponse(
    call: Call<ArticleResponse>,
    response: Response<ArticleResponse>
) {
    if (response.isSuccessful && response.body() != null) {
        callback(response.body()!!.data)
    } else {
        val errorMessage = when (response.code()) {
            401 -> "Unauthorized. Please log in again."
            404 -> "Resource not found."
            500 -> "Server error. Please try again later."
            else -> "Error: ${response.message()}"
        }
        Log.e("API Error", "HTTP error occurred: $errorMessage")
        onError(errorMessage)
    }
}

四.总结

通过深入学习Retrofit及其与Kotlin的结合使用,我掌握了如何在Android应用中高效地进行RESTful API通信。这不仅提高了我的开发效率,还增强了我对网络编程的理解。面对挑战时,不断探索和尝试新方法是解决问题的关键。协程的支持使得异步编程更加直观和简洁,极大提升了用户体验。

五.参考文献

  1. Square Retrofit官方文档
...全文
716 回复 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

111

社区成员

发帖
与我相关
我的任务
社区描述
202401_CS_SE_FZU
软件工程 高校
社区管理员
  • FZU_SE_TeacherL
  • 言1837
  • 防震水泥
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧