Retrofit通过Header和Field获取响应消息时Toast显示空白问题
Let's break down why your Toast is showing an empty message even though Postman works, and fix it step by step:
1. Critical: Fix the Typo in Your API Parameter
Looking at your API.kt code, there's a trailing space in the username field:
@Field("username ") username: String?, // Notice the space after "username"!
In Postman, you're probably using the correct parameter name username (without the space), which is why it works. But in your app, the request is sending a parameter named username (with space), so the backend likely can't recognize it—leading to an unexpected response where message is null or empty.
Fix: Remove the space in the @Field annotation:
@Field("username") username: String?,
2. Check if the Response is Actually Successful
Right now, your code assumes response.body() is always non-null, but Retrofit only returns a non-null body for 2xx status codes. If the API returns a 4xx/5xx error (like unauthorized, bad request), response.body() will be null, making response.body()?.message empty.
Update your onResponse method to handle both success and error cases, and log details for debugging:
override fun onResponse(call: Call<ClockInRes>, response: Response<ClockInRes>) { if (response.isSuccessful) { val clockInResponse = response.body() // Log the full response to check what's coming back Log.d("ClockInDebug", "Full response: $clockInResponse") isitapin.text = clockInResponse?.data?.clock_in // Show a fallback message if message is null val toastMessage = clockInResponse?.message ?: "Clock-in successful!" Toast.makeText(activity, toastMessage, Toast.LENGTH_SHORT).show() } else { // Handle error responses (e.g., 400, 401) val errorDetails = response.errorBody()?.string() Log.d("ClockInDebug", "Error response code: ${response.code()}, details: $errorDetails") Toast.makeText(activity, "Request failed: ${response.message()}", Toast.LENGTH_SHORT).show() } }
3. Add Retrofit Logging to Compare Requests with Postman
To confirm your app's request matches what you send in Postman, add a logging interceptor to your Retrofit client. This will print the full request (headers, body) and response (headers, body) to your logcat.
Update your RetroFitClient class:
import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory class RetroFitClient { private val BASE_URL = "YOUR_BASE_URL_HERE" // Replace with your actual base URL val apiService: API by lazy { val loggingInterceptor = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY // Logs full request/response } val okHttpClient = OkHttpClient.Builder() .addInterceptor(loggingInterceptor) .build() Retrofit.Builder() .baseUrl(BASE_URL) .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) .build() .create(API::class.java) } }
Now check Logcat for the ClockInDebug tag—compare the request headers, body, and response with what you see in Postman. Any mismatch (like missing parameters, wrong headers) will be obvious here.
4. Verify Your ClockInRes Model Class
Make sure your ClockInRes data class correctly maps to the JSON response from the API. For example, if the backend returns {"message": "Success", "data": {...}}, your model should look like this:
data class ClockInRes( val message: String?, val data: ClockInData? ) data class ClockInData( val clock_in: String? )
If the field names don't match (e.g., backend uses msg instead of message), Gson won't parse the value, leaving message as null. You can use tools like GsonFormat to generate the model class directly from your Postman response JSON.
5. Double-Check Request Parameters
From your println statement, confirm all parameters (token, username, ip address, latitude, longitude) are non-null and match what you send in Postman. If any parameter is null, it might cause the backend to return an invalid response with an empty message.
内容的提问来源于stack exchange,提问作者Newton Ongko

