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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:02:17