Android Java Retrofit校验用户存在遇内部类变量final报错如何解决
问题原因分析
- 第一个编译报错是Java语法规则限制:匿名内部类引用的外部局部变量必须是
final或等效final(仅赋值一次),你需要修改val的值,直接用基本类型boolean肯定不符合规则。IDE自动修改为数组形式是利用了引用类型final仅限制引用地址不变,数组内部元素可修改的特性,能解决编译报错,但逻辑完全不可用。 - 核心逻辑问题:你调用的
responseCall.enqueue()是异步请求,方法不会等待请求返回就会直接执行return val,你拿到的永远是初始化的默认值,根本不是请求返回的结果。
推荐解决方案:用回调接口接收异步结果
这是Android网络请求最常用的实现方式,不会阻塞主线程,符合Retrofit异步设计逻辑。
1. 先定义结果回调接口
public interface OnUserExistCheckListener { void onCheckResult(boolean isUserExist); }
2. 修改原方法,取消返回值,新增回调参数
public void checkUserExist(String type, String username, Context context, OnUserExistCheckListener listener) { final ProgressDialog dialog = Functions.showProgressDialog(context, context.getString(R.string.please_wait), context.getString(R.string.please_wait)); dialog.show(); RestApi restApi = RetroFit.getInstanceRetrofit(); Call<SignIn> responseCall = restApi.getUserData( type, username ); responseCall.enqueue(new Callback<SignIn>() { @Override public void onResponse(Call<id.wifi.myapp.model.SignIn> call, Response<SignIn> response) { dialog.dismiss(); boolean isExist; if (response.isSuccessful()) { String result = response.body().getResult(); if (result.equals("1")) { Toast.makeText(context, context.getString(R.string.error_user_exist), Toast.LENGTH_LONG).show(); isExist = true; } else { Toast.makeText(context, "OK you're new", Toast.LENGTH_LONG).show(); isExist = false; } } else { Toast.makeText(context, context.getString(R.string.error_msg) + " (" + Functions.networkError(response.code(), response.message()) + ")", Toast.LENGTH_LONG).show(); isExist = false; } // 回传结果 if (listener != null) { listener.onCheckResult(isExist); } } @Override public void onFailure(Call<id.wifi.myapp.model.SignIn> call, Throwable t) { dialog.dismiss(); Toast.makeText(context, context.getString(R.string.error_msg2), Toast.LENGTH_LONG).show(); if (listener != null) { listener.onCheckResult(false); } } }); }
3. 调用示例
// 在需要检查用户存在性的位置调用 checkUserExist("你的类型参数", "要校验的用户名", 当前上下文, new OnUserExistCheckListener() { @Override public void onCheckResult(boolean isUserExist) { // 这里拿到结果执行后续逻辑 if (isUserExist) { // 执行用户已存在的对应逻辑 } else { // 执行用户不存在的对应逻辑 } } });
可选方案:同步请求(不推荐,必须在子线程执行)
如果你确实需要方法直接返回布尔值,可改用Retrofit同步执行方法,注意绝对不能在主线程调用,否则会触发ANR报错:
public boolean isUserExistBool(String type, String username) throws IOException { RestApi restApi = RetroFit.getInstanceRetrofit(); Call<SignIn> responseCall = restApi.getUserData(type, username); // 同步执行,阻塞当前线程 Response<SignIn> response = responseCall.execute(); if (response.isSuccessful()) { return "1".equals(response.body().getResult()); } return false; }
调用时需要自行调度到子线程执行,拿到结果后再切回主线程更新UI。
内容的提问来源于stack exchange,提问作者Muhammad Faisal
相关产品推荐
相关产品推荐

