如何等待Retrofit接口调用响应完成后再执行后续操作
问题核心原因
你当前使用enqueue方法发起异步Retrofit请求,该方法不会阻塞当前线程,会直接执行后续代码,所以不等接口返回结果就会执行return逻辑,自然无法保证接口调用成功后再执行后续Ticket插入逻辑。
可选实现方案
方案1:同步执行请求(适合简单场景,需注意线程调度)
直接使用execute方法同步执行请求,该方法会阻塞当前线程直到拿到接口响应,之后再返回结果。
注意
绝对不能在安卓主线程调用该方法,否则会触发NetworkOnMainThreadException异常,必须将整个saveListToDb逻辑放到子线程执行。
修改后的insertApi代码
public long insertApi(TicketListTable ticketListTable) throws IOException { Call<TicketListTable> ticketListTableCall = dataService.createTicketList(ticketListTable); // 同步执行网络请求,阻塞当前线程直到拿到响应 Response<TicketListTable> response = ticketListTableCall.execute(); if (response.isSuccessful()) { // 接口请求成功后再插入本地数据库,返回有效ID return repo.insert(ticketListTable); } else { // 接口请求失败返回无效ID,供上层判断 return -1; } }
方案2:异步回调链式调用(推荐,不会阻塞线程)
通过自定义回调接口,把后续插入Ticket的逻辑放到TicketList接口请求成功的回调中执行,避免线程阻塞问题。
第一步:定义回调接口
public interface InsertTicketListCallback { void onSuccess(long listId); void onFailure(Throwable error); }
第二步:改造insertApi方法
public void insertApi(TicketListTable ticketListTable, InsertTicketListCallback callback) { Call<TicketListTable> ticketListTableCall = dataService.createTicketList(ticketListTable); ticketListTableCall.enqueue(new Callback<TicketListTable>() { @Override public void onResponse(Call<TicketListTable> call, Response<TicketListTable> response) { if (response.isSuccessful()) { long listId = repo.insert(ticketListTable); callback.onSuccess(listId); } else { callback.onFailure(new Exception("接口请求失败,错误码:" + response.code())); } } @Override public void onFailure(Call<TicketListTable> call, Throwable t) { callback.onFailure(t); } }); }
第三步:改造saveListToDb方法
public void saveListToDb(String[] split, String regexData){ String newListName = listName.getText().toString(); SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); TicketListTable newTicketListTable = new TicketListTable(); newTicketListTable.setTicketListName(newListName); newTicketListTable.setTicketListCreated(sd.format(Calendar.getInstance().getTime())); newTicketListTable.setTicketListUpdated(sd.format(Calendar.getInstance().getTime())); // 调用异步接口,在成功回调中执行后续Ticket插入逻辑 ticketTableVm.insertApi(newTicketListTable, new InsertTicketListCallback() { @Override public void onSuccess(long ticketTableListId) { if(ticketTableListId <= 0){ // 自定义处理本地插入失败逻辑 return; } // 批量插入Ticket for (String s : split) { String[] values = s.split(regexData); String number = values[0].replace("\n", "").replace("\r", ""); String info = values[1]; String warningNote = values[2]; String warning = values[3]; String customer = values[4]; int useable = Integer.parseInt(values[5].replaceAll("\\s+", "").replace("\n", "").replace("\r", "")); TicketTable ticketTable = new TicketTable(number, customer, info, warningNote, useable, ticketTableListId,warning); ticketTableVm.insert(ticketTable); } // 所有操作完成后自定义处理逻辑,如UI提示 } @Override public void onFailure(Throwable t) { // 自定义处理请求失败逻辑,如日志打印、用户提示 t.printStackTrace(); } }); }
额外注意事项
- 异步回调中如果需要更新UI,安卓平台下Retrofit默认回调运行在主线程,可直接操作UI;如果需要执行批量数据库插入等耗时操作,建议切到子线程执行避免卡顿。
- 如果项目已接入Kotlin,可直接使用Retrofit的suspend挂起方法结合协程实现,代码更简洁,无需嵌套回调。
内容的提问来源于stack exchange,提问作者Vishav Lakhtia
相关产品推荐
相关产品推荐

