使用RETROFIT + COROUTINE发起网络请求无法获取数据无响应求助
问题排查&修复方案
1. 检查基础配置
- 首先确认
AndroidManifest.xml中已经添加网络权限,这是发起网络请求的必备条件:
<uses-permission android:name="android.permission.INTERNET" />
如果你的应用targetSdkVersion >=28且需要访问http接口,还需要在application标签下添加属性:
android:usesCleartextTraffic="true"
2. 补全异常捕获和日志逻辑
你现有代码仅处理了响应成功的场景,一旦出现网络不通、解析失败、接口返回非2xx状态码等情况,都没有任何日志输出,自然看不到相关信息。同时不建议直接使用GlobalScope,容易造成内存泄漏,推荐用lifecycleScope绑定Activity生命周期自动销毁。
首先在build.gradle(Module级)添加必要依赖:
dependencies { // lifecycle协程依赖,用于lifecycleScope implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.2" // OkHttp日志拦截器,可打印完整的请求、响应信息 implementation "com.squareup.okhttp3:logging-interceptor:4.11.0" }
修改后的Activity代码如下:
import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import androidx.lifecycle.lifecycleScope import com.google.gson.annotations.SerializedName import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Response import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import retrofit2.http.GET class MainActivity : AppCompatActivity() { val TAG = "MainActivity" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 配置日志拦截器,打印全量请求响应信息 val loggingInterceptor = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY } val okHttpClient = OkHttpClient.Builder() .addInterceptor(loggingInterceptor) .build() val api = Retrofit.Builder() .client(okHttpClient) .baseUrl("https://howtodoandroid.com/") .addConverterFactory(GsonConverterFactory.create()) .build() .create(RetrofitService::class.java) // 用lifecycleScope代替GlobalScope,避免内存泄漏 lifecycleScope.launch(Dispatchers.IO) { try { val response = api.getAllMovies() Log.d(TAG, "接口响应码:${response.code()}") if (response.isSuccessful) { val movies = response.body() Log.d(TAG, "响应体是否为空:${movies == null}") movies?.forEach { movie -> Log.d(TAG, "电影名称:${movie.name}") } } else { // 打印失败响应的错误信息 Log.e(TAG, "请求失败,错误信息:${response.errorBody()?.string()}") } } catch (e: Exception) { // 捕获所有异常:网络异常、解析异常等 Log.e(TAG, "请求抛出异常:", e) } } } } interface RetrofitService { @GET("movielist.json") suspend fun getAllMovies() : Response<List<Movie>> } // 如果接口返回字段和定义不一致,可加@SerializedName注解映射 data class Movie( val name: String, val imageUrl: String, val category: String )
3. 核对数据类和接口返回的匹配性
如果接口返回的字段名、字段类型和你定义的Movie数据类不匹配,Gson解析会直接抛出异常,没有捕获的话也不会有输出。可以通过日志拦截器打印的返回结果,核对字段是否匹配,必要时用@SerializedName做字段映射。
修改后运行App,查看Logcat的日志即可定位具体问题。
内容的提问来源于stack exchange,提问作者Chelsea Katsidzira
相关产品推荐
相关产品推荐

