如何在AsyncHttpClient(loopj)的onSuccess外部使用获取的JSON数据?
问题:如何在AsyncHttpClient的onSuccess外部使用异步获取的数据?
我当前使用loopj的Android异步框架AsyncHttpClient读取JSON数据,代码如下:
public class HorariosActivity extends AppCompatActivity { String hora_inicio; String hora_fin; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_horarios); obtDatosBD(); // 这里想使用hora_inicio和hora_fin,但拿不到值 } private void obtDatosBD(){ final AsyncHttpClient client = new AsyncHttpClient(); client.get("http://192.168.0.26/WS_policlinica/horas.php", new AsyncHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { if(statusCode==200){ try { JSONArray jsonArray = new JSONArray(new String(responseBody)); for (int i=0; i<jsonArray.length(); i++){ hora_inicio = jsonArray.getJSONObject(i).getString("FISIO_HORA_INICIO"); hora_fin = jsonArray.getJSONObject(i).getString("FISIO_HORA_FIN"); } }catch (Exception e){ e.printStackTrace(); } } } @Override public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { } }); } }我可以在onSuccess方法中接收并存储hora_inicio和hora_fin数据,但不知如何在onSuccess方法外部使用这些值,尤其想在onCreate中使用却无法实现,求解决方法。
解决方案
这个问题其实是异步编程里的典型坑——AsyncHttpClient的网络请求是异步执行的,也就是说你在onCreate里调用obtDatosBD()之后,代码会立刻继续往下跑,根本不会等网络请求返回结果。等onSuccess回调触发、你把数据存到hora_inicio和hora_fin里的时候,onCreate早就执行完了,这时候你再去拿这两个值自然是空的。
下面给你几种实用的解决办法:
方法一:在onSuccess里直接调用处理数据的方法
最简单直接的方式,就是把需要使用数据的逻辑封装成独立方法,在onSuccess拿到数据后立刻调用它。比如:
public class HorariosActivity extends AppCompatActivity { String hora_inicio; String hora_fin; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_horarios); obtDatosBD(); } private void obtDatosBD(){ final AsyncHttpClient client = new AsyncHttpClient(); client.get("http://192.168.0.26/WS_policlinica/horas.php", new AsyncHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { if(statusCode==200){ try { JSONArray jsonArray = new JSONArray(new String(responseBody)); for (int i=0; i<jsonArray.length(); i++){ hora_inicio = jsonArray.getJSONObject(i).getString("FISIO_HORA_INICIO"); hora_fin = jsonArray.getJSONObject(i).getString("FISIO_HORA_FIN"); } // 拿到数据后直接调用处理方法 useHorarioData(); }catch (Exception e){ e.printStackTrace(); } } } @Override public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { Toast.makeText(HorariosActivity.this, "网络请求失败", Toast.LENGTH_SHORT).show(); } }); } // 专门处理时间数据的方法 private void useHorarioData(){ // 这里可以正常使用hora_inicio和hora_fin,比如更新UI // TextView tvInicio = findViewById(R.id.tv_hora_inicio); // tvInicio.setText("开始时间:" + hora_inicio); // TextView tvFin = findViewById(R.id.tv_hora_fin); // tvFin.setText("结束时间:" + hora_fin); Toast.makeText(this, "开始时间:" + hora_inicio + " | 结束时间:" + hora_fin, Toast.LENGTH_SHORT).show(); } }
方法二:自定义回调接口
如果你的数据处理逻辑需要复用,或者要在多个地方使用,可以自定义一个回调接口,把数据传递到需要的地方:
public class HorariosActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_horarios); // 调用请求方法时传入回调 obtDatosBD(new HorarioCallback() { @Override public void onHorarioLoaded(String inicio, String fin) { // 在这里拿到数据并使用 Toast.makeText(HorariosActivity.this, "开始时间:" + inicio + " | 结束时间:" + fin, Toast.LENGTH_SHORT).show(); } @Override public void onLoadFailed() { Toast.makeText(HorariosActivity.this, "加载失败,请重试", Toast.LENGTH_SHORT).show(); } }); } // 把回调接口作为参数传入请求方法 private void obtDatosBD(final HorarioCallback callback){ final AsyncHttpClient client = new AsyncHttpClient(); client.get("http://192.168.0.26/WS_policlinica/horas.php", new AsyncHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { if(statusCode==200){ try { JSONArray jsonArray = new JSONArray(new String(responseBody)); String hora_inicio = ""; String hora_fin = ""; for (int i=0; i<jsonArray.length(); i++){ hora_inicio = jsonArray.getJSONObject(i).getString("FISIO_HORA_INICIO"); hora_fin = jsonArray.getJSONObject(i).getString("FISIO_HORA_FIN"); } // 回调成功方法,传递数据 callback.onHorarioLoaded(hora_inicio, hora_fin); }catch (Exception e){ e.printStackTrace(); callback.onLoadFailed(); } } } @Override public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { callback.onLoadFailed(); } }); } // 自定义回调接口 interface HorarioCallback{ void onHorarioLoaded(String horaInicio, String horaFin); void onLoadFailed(); } }
方法三:使用LiveData(推荐,适配Jetpack架构)
如果你在用Android Jetpack,用LiveData来观察数据变化会更符合现代Android开发规范,还能自动处理生命周期:
首先确保build.gradle里添加了LiveData依赖:
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.2" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"
然后修改代码:
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.Observer; public class HorariosActivity extends AppCompatActivity { // 创建LiveData对象保存时间数据 private MutableLiveData<Horario> horarioLiveData = new MutableLiveData<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_horarios); // 观察LiveData的数据变化,自动感知生命周期 horarioLiveData.observe(this, new Observer<Horario>() { @Override public void onChanged(Horario horario) { // 数据更新时触发这里,直接使用数据 Toast.makeText(HorariosActivity.this, "开始时间:" + horario.getHoraInicio() + " | 结束时间:" + horario.getHoraFin(), Toast.LENGTH_SHORT).show(); } }); obtDatosBD(); } private void obtDatosBD(){ final AsyncHttpClient client = new AsyncHttpClient(); client.get("http://192.168.0.26/WS_policlinica/horas.php", new AsyncHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { if(statusCode==200){ try { JSONArray jsonArray = new JSONArray(new String(responseBody)); String hora_inicio = ""; String hora_fin = ""; for (int i=0; i<jsonArray.length(); i++){ hora_inicio = jsonArray.getJSONObject(i).getString("FISIO_HORA_INICIO"); hora_fin = jsonArray.getJSONObject(i).getString("FISIO_HORA_FIN"); } // 更新LiveData的数据 horarioLiveData.setValue(new Horario(hora_inicio, hora_fin)); }catch (Exception e){ e.printStackTrace(); } } } @Override public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { Toast.makeText(HorariosActivity.this, "网络请求失败", Toast.LENGTH_SHORT).show(); } }); } // 封装时间数据的实体类 static class Horario{ private String horaInicio; private String horaFin; public Horario(String horaInicio, String horaFin) { this.horaInicio = horaInicio; this.horaFin = horaFin; } public String getHoraInicio() { return horaInicio; } public String getHoraFin() { return horaFin; } } }
内容的提问来源于stack exchange,提问作者Mimmetico
相关产品推荐
相关产品推荐

