Android基于Retrofit API响应验证手机号及进度条实现问题
解决Retrofit异步调用时的进度条显示与流程阻塞问题
嘿,刚接触Android的话,异步请求的处理确实容易踩坑。你原来的代码里用while (existmsg == null)循环等待API响应的方式完全错误,会直接卡死主线程(触发ANR错误),而且根本没法正确显示进度条。下面我给你一步步修改代码,彻底解决这个问题:
首先理清楚正确的流程逻辑:
- 用户点击提交按钮,先做本地输入验证(手机号长度、密码长度等客户端规则检查)
- 本地验证通过后,显示进度条+禁用提交按钮(防止重复点击)
- 调用Retrofit异步API验证手机号是否存在
- API响应返回后,隐藏进度条+启用按钮,根据结果分支处理:
- 手机号已存在:提示用户登录
- 手机号不存在:跳转到OtpActivity
- 请求出错:提示用户重试
1. 重构RegisterActivity.java
移除容易引发问题的静态变量existmsg,重新梳理点击事件和验证逻辑:
package com.example.narmail.truck30mint; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.Toast; import com.example.narmail.truck30mint.Api.services.UserApi; import com.example.narmail.truck30mint.Api.services.NetworkStatus; public class RegisterActivity extends AppCompatActivity { EditText registerMobileInput, registerPasswordInput; Button registerButton; ProgressBar progressBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_register); progressBar = findViewById(R.id.progressBar); registerMobileInput = findViewById(R.id.registerMobileInput); registerPasswordInput = findViewById(R.id.registerPasswordInput); registerButton = findViewById(R.id.registerButton); registerButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (NetworkStatus.isOnline(getApplicationContext())) { // 先执行本地输入验证 if (validateLocalInputs()) { String mobile = registerMobileInput.getText().toString().trim(); String password = registerPasswordInput.getText().toString().trim(); // 显示进度条,禁用按钮防止重复点击 progressBar.setVisibility(View.VISIBLE); registerButton.setEnabled(false); // 调用API验证手机号 UserApi.checkMobileExist(mobile, new UserApi.MobileExistCallback() { @Override public void onMobileExist() { progressBar.setVisibility(View.GONE); registerButton.setEnabled(true); Toast.makeText(getApplicationContext(), "手机号已存在,请登录", Toast.LENGTH_LONG).show(); } @Override public void onMobileNotExist() { progressBar.setVisibility(View.GONE); registerButton.setEnabled(true); Intent data = new Intent(RegisterActivity.this, OtpActivity.class); data.putExtra("mobile", mobile); data.putExtra("pass", password); startActivity(data); } @Override public void onError() { progressBar.setVisibility(View.GONE); registerButton.setEnabled(true); Toast.makeText(getApplicationContext(), "出现错误,请重试", Toast.LENGTH_LONG).show(); } }); } } else { Toast.makeText(getApplicationContext(), "请连接网络", Toast.LENGTH_LONG).show(); } } }); } // 仅做客户端本地输入规则验证 private boolean validateLocalInputs() { String mobile = registerMobileInput.getText().toString().trim(); String password = registerPasswordInput.getText().toString().trim(); if (mobile.isEmpty()) { Toast.makeText(getApplicationContext(), "手机号不能为空", Toast.LENGTH_LONG).show(); return false; } if (mobile.length() != 10) { Toast.makeText(getApplicationContext(), "请输入正确的10位手机号", Toast.LENGTH_LONG).show(); return false; } if (password.isEmpty()) { Toast.makeText(getApplicationContext(), "密码不能为空", Toast.LENGTH_LONG).show(); return false; } if (password.length() < 6) { Toast.makeText(getApplicationContext(), "密码至少需要6位", Toast.LENGTH_LONG).show(); return false; } return true; } }
2. 补全并修复UserApi.java
添加回调接口来传递API结果,同时优化Retrofit的初始化逻辑:
package com.example.narmail.truck30mint.Api.services; import android.util.Log; import com.example.narmail.truck30mint.Api.interfaces.UserClient; import com.example.narmail.truck30mint.Api.models.MobileExist; import com.google.gson.GsonBuilder; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; public class UserApi { private static final String BASE_URL = "http://10.0.2.2:3002/"; private static Retrofit retrofit; private static UserClient apiInterface; // 单例初始化Retrofit,避免重复创建实例 private static void initRetrofit() { if (retrofit == null) { retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().create())) .build(); apiInterface = retrofit.create(UserClient.class); } } // 定义回调接口,让Activity接收API结果 public interface MobileExistCallback { void onMobileExist(); void onMobileNotExist(); void onError(); } // 验证手机号是否存在的核心方法 public static void checkMobileExist(String mobile, final MobileExistCallback callback) { initRetrofit(); Call<MobileExist> call = apiInterface.checkMobileExist(mobile); call.enqueue(new Callback<MobileExist>() { @Override public void onResponse(Call<MobileExist> call, Response<MobileExist> response) { if (response.isSuccessful() && response.body() != null) { String status = response.body().getStatus(); if ("exist".equalsIgnoreCase(status)) { callback.onMobileExist(); } else if ("notExist".equalsIgnoreCase(status)) { callback.onMobileNotExist(); } else { callback.onError(); } } else { callback.onError(); } } @Override public void onFailure(Call<MobileExist> call, Throwable t) { Log.e("UserApi", "请求失败: " + t.getMessage()); callback.onError(); } }); } }
3. 修正实体类命名(遵循Java规范)
将原来的mobileExist改为大驼峰命名的MobileExist:
package com.example.narmail.truck30mint.Api.models; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; public class MobileExist { @SerializedName("status") @Expose private String status; public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } }
4. 确保UserClient接口匹配API定义
你的UserClient接口需要和后端API的请求方式对应,比如:
package com.example.narmail.truck30mint.Api.interfaces; import com.example.narmail.truck30mint.Api.models.MobileExist; import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.Query; public interface UserClient { // 假设后端是GET请求,参数为mobile @GET("check-mobile") Call<MobileExist> checkMobileExist(@Query("mobile") String mobile); }
关键改进点说明:
- 移除了阻塞主线程的
while循环,改用Retrofit原生异步回调处理结果 - 用回调接口替代静态变量
existmsg,避免内存泄漏和线程安全问题 - 在API请求前后正确控制进度条显示/隐藏,同时禁用按钮防止重复提交
- 拆分本地验证和API验证逻辑,代码结构更清晰
- 遵循Java命名规范,提升代码可维护性
这样修改后,就能正常处理异步请求,进度条也能正确显示,不会再出现界面卡死的问题啦~
内容的提问来源于stack exchange,提问作者Narmail Sandhu
相关产品推荐
相关产品推荐

