Android 凌空同步请求不工作

发布时间: 2017/3/19 17:51:46
注意事项: 本文中文内容可能为机器翻译,如要查看英文原文请点击上面连接.

我试图向使用RequestFuture的服务器的同步请求,但它不工作。相同请求时使用异步工作正常。

这是我的代码︰

 public void fetchModules(){
   JSONObject response = null;
    RequestQueue requestQueue = Volley.newRequestQueue(getContext());

    RequestFuture<JSONObject> future = 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());
}

我得到一个空指针异常︰

一样︰ 尝试在 android.support.v4.app.BackStackRecord.run(BackStackRecord.java:801) android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1290) android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1108) android.support.v4.app.Fragment.performCreateView(Fragment.java:2080) com.maths.app.AllModules.onCreateView(AllModules.java:51) com.maths.app.AllModules.fetchModules(AllModules.java:85) 空对象引用上调用虚方法 'java.lang.String org.json.JSONObject.toString()' 在 java.lang.reflect.Method.invoke (本机方法) 在 com.android.intern android.app.ActivityThread.main(ActivityThread.java:5443) android.os.Looper.loop(Looper.java:148) android.os.Handler.dispatchMessage(Handler.java:95) android.os.Handler.handleCallback(Handler.java:746) android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:536) android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1677)在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) al.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)

它返回一个 null 响应。有人可以请帮忙解决这个问题吗?

解决方法 1:

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);


        RequestFuture<JSONObject> future = 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<String,String, JSONObject> {

    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
    }
}

主要 Activity :

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"},[...]

希望这有助于

干杯 !

赞助商