我试图使用RequestFuture向服务器发出同步请求,但它无法正常工作.使用异步完成时相同的请求工作正常.
这是我的代码:
public void fetchModules(){ JSONObject response = null; RequestQueue requestQueue = Volley.newRequestQueue(getContext()); RequestFuturefuture = RequestFuture.newFuture(); JsonObjectRequest request = new JsonObjectRequest(Url.ALL_MODULES_URL,null,future,future); requestQueue.add(request); try { response = future.get(3, TimeUnit.SECONDS); // Blocks for at most 10 seconds. } catch (InterruptedException e) { Log.d(TAG,"interupted"); } catch (ExecutionException e) { Log.d(TAG,"execution"); } catch (TimeoutException e) { e.printStackTrace(); } Log.d(TAG,response.toString()); }
我得到一个nullpointerexception:
java.lang.NullPointerException:尝试在com.maths.app.AllModules.fetchModules(AllModules.java:85)的空对象引用上调用虚方法'java.lang.String org.json.JSONObject.toString()'在android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager)的android.support.v4.app.Fragment.performCreateView(Fragment.java:2080)上的com.maths.app.AllModules.onCreateView(AllModules.java:51). java:1108)在android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1290)的android.support.v4.app.BackStackRecord.run(BackStackRecord.java:801)android.support.v4.app在Android.os的android.os.Handler.handleCallback(Handler.java:746)的android.support.v4.app.FragmentManagerImpl $ 1.run(FragmentManager.java:536)的.FragmentManagerImpl.execPendingActions(FragmentManager.java:1677) .Handler.dispatchMessage(Handler.java:95)位于android.app.Looper.loop(Looper.java:148)的android.app.ActivityThread.main(ActivityThread.java:5443),位于java.lang.reflect.Method.调用(娜 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)的com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:728)中的tive方法)
它返回一个null响应.我怎么解决这个问题?
TL;博士; 你被try-catch欺骗了
说明:因为RequestFuture.get()
它可能正在UI线程上运行,所以你真的得到了一个java.util.concurrent.TimeoutException
幕后.这是在主线程上执行调用时的默认行为.
try catch会阻止应用程序崩溃,但是当您尝试结果时,响应仍然是一个空引用会导致应用程序崩溃Log
.如果您评论以下行,您将看到应用程序不再崩溃(那里).
Log.d(TAG,response.toString());
修复:在另一个线程上调用RequestFuture网络!
一种方法:
public class TestVolley { private String TAG = "SO_TEST"; private String url = "http://pokeapi.co/api/v2/pokemon-form/1/"; public JSONObject fetchModules(Context ctx){ JSONObject response = null; RequestQueue requestQueue = Volley.newRequestQueue(ctx); RequestFuturefuture = RequestFuture.newFuture(); JsonObjectRequest request = new JsonObjectRequest(url,null,future,future); requestQueue.add(request); try { response = future.get(3, TimeUnit.SECONDS); // Blocks for at most 10 seconds. } catch (InterruptedException e) { Log.d(TAG,"interrupted"); } catch (ExecutionException e) { Log.d(TAG,"execution"); } catch (TimeoutException e) { e.printStackTrace(); } Log.d(TAG,response.toString()); return response; } }
在AsyncTask
这将使网络调用:
public class MyVolleyAsyncTask extends AsyncTask{ private Context ctx; public MyVolleyAsyncTask(Context hostContext) { ctx = hostContext; } @Override protected JSONObject doInBackground(String... params) { // Method runs on a separate thread, make all the network calls you need TestVolley tester = new TestVolley(); return tester.fetchModules(ctx); } @Override protected void onPostExecute(JSONObject result) { // runs on the UI thread // do something with the result } }
主要活动:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // this is your old code which will crash the app //TestVolley tester = new TestVolley(); //tester.fetchModules(this); // Works! new MyVolleyAsyncTask(this).execute(); } }
结果:
com.so.henriquems.testvolleyfuture D/SO_TEST: {"id":1,"pokemon":{"url":"http:\/\/pokeapi.co\/api\/v2\/pokemon\/1\/","name":"bulbasaur"},[...]
希望这可以帮助
干杯!