You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中Retrofit GET请求偶尔无返回问题排查求助

Hey there! Let's break down why your Retrofit GET request is acting inconsistent—since you're coming from PHP/JS, there are a few Android/Kotlin-specific gotchas tripping you up here. Let's go through them step by step, with fixes you can implement right away.

First: Your Connector Class is Creating New Retrofit/OkHttp Instances Every Time

Looking at your mainConnector class, you're creating a brand new OkHttpClient and Retrofit object every time you make a request. This is bad practice because:

  • It wastes system resources (connections, threads)
  • It bypasses OkHttp's connection pooling, which can lead to unstable connections
  • Kotlin class/method naming is off: fun MainConnector() is a regular method, not a constructor, which adds confusion

Fix this by making your Retrofit/OkHttp setup a singleton (only created once):

interface ApiService {
    companion object {
        const val BASE_URL = "你的基础URL(记得以/结尾!)"
    }

    // Avoid nullable types unless your API explicitly returns null lists
    @GET("main")
    fun getPosts(): Call<List<Products>>
}

class MainConnector {
    // Singleton pattern to reuse Retrofit/OkHttp instances
    companion object {
        private val retrofit: Retrofit by lazy {
            val logging = HttpLoggingInterceptor().apply {
                level = HttpLoggingInterceptor.Level.BODY
            }

            val okHttpClient = OkHttpClient.Builder()
                .addInterceptor(logging)
                // Add timeouts to prevent silent failures from slow networks
                .connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                .build()

            Retrofit.Builder()
                .baseUrl(ApiService.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .client(okHttpClient)
                .build()
        }

        val apiService: ApiService by lazy {
            retrofit.create(ApiService::class.java)
        }
    }
}

Second: You're Ignoring Failure Cases & Overusing !!

Your onFailure method is empty—this is a critical mistake! When requests fail (timeouts, network drops, server errors), you get no feedback at all. Also, using !! everywhere forces non-null checks, which will crash your app silently if any field is null, making you think the request "returned nothing" when it actually crashed.

Fix your Activity code with proper error handling and safe null checks:

val apiService = MainConnector.apiService
val call = apiService.getPosts()

call.enqueue(object : Callback<List<Products>> {
    override fun onResponse(call: Call<List<Products>>, response: Response<List<Products>>) {
        // First check if the server returned a successful status code (200-299)
        if (response.isSuccessful) {
            val postList = response.body()
            if (postList != null && postList.isNotEmpty()) {
                val listView: ListView = findViewById(R.id.listview)
                listView.isClickable = true

                // No need to re-create the list—use the parsed data directly
                val adapter = MyMainListAdapter(this@MainActivity, R.layout.custom_main_list, postList.toMutableList())
                listView.adapter = adapter

                listView.setOnItemClickListener { _, _, position, _ ->
                    val product = postList[position]
                    val intent = Intent(this@MainActivity, ProductActivity::class.java)
                    
                    // Safe handling for nullable image lists
                    val imageList = product.image?.let { ArrayList(it) } ?: ArrayList()
                    intent.putStringArrayListExtra("image", imageList)
                    
                    // Pass other fields safely (no need for !! here)
                    intent.putExtra("name", product.pname)
                    intent.putExtra("createdAt", product.created_at)
                    intent.putExtra("description", product.description)
                    // ... add the rest of your fields here
                    
                    startActivity(intent)
                }
            } else {
                // Server returned an empty list—notify the user
                Toast.makeText(this@MainActivity, "暂无数据", Toast.LENGTH_SHORT).show()
            }
        } else {
            // Server returned an error (404, 500, etc.)
            val errorMsg = "请求失败:状态码 ${response.code()} - ${response.message()}"
            Log.e("MainActivity", errorMsg)
            Toast.makeText(this@MainActivity, errorMsg, Toast.LENGTH_SHORT).show()
        }
    }

    override fun onFailure(call: Call<List<Products>>, t: Throwable) {
        // Log the full error to debug what's going wrong
        val errorMsg = "请求失败:${t.message}"
        Log.e("MainActivity", errorMsg, t) // Prints full stack trace for debugging
        Toast.makeText(this@MainActivity, errorMsg, Toast.LENGTH_SHORT).show()
    }
})

Third: Additional Checks to Rule Out Other Issues

  1. Verify Network Permissions: Make sure your AndroidManifest.xml includes the internet permission:
    <uses-permission android:name="android.permission.INTERNET" />
    
  2. Check Gson Parsing: Ensure your Products class fields exactly match the API's JSON response (case-sensitive!). If a field name doesn't match, Gson will parse it as null. Use @SerializedName if needed:
    data class Products(
        @SerializedName("admindescription") val admindescription: String,
        // ... rest of your fields
    )
    
  3. Compare Request Details: Use the HttpLoggingInterceptor output in Logcat to compare your Retrofit request headers/URL with the web browser's request. Some servers block requests from non-browser User-Agents—you can add a custom User-Agent to OkHttp if needed:
    val okHttpClient = OkHttpClient.Builder()
        .addInterceptor { chain ->
            val request = chain.request().newBuilder()
                .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
                .build()
            chain.proceed(request)
        }
        // ... other config
    

Why This Fixes Your Problem

  • Reusing Retrofit/OkHttp instances ensures stable connection pooling and reduces resource waste.
  • Timeout settings prevent silent failures from slow or unstable networks.
  • Proper error handling in onFailure and onResponse tells you exactly why a request failed, instead of leaving you guessing.
  • Safe null checks avoid hidden crashes that look like "no data returned".

内容的提问来源于stack exchange,提问作者AhmadVahedi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 06:53:39