繁体   English   中英

Android Volley同步请求无法正常工作

[英]Android Volley synchronous request not working

我试图使用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());
}

我得到一个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);


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

主要活动:

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

希望这可以帮助

干杯!

我们可以使用RxJava。

让我们假设fetchModules方法返回JSONObject

Observable<JSONObject> moduleObservable = Observable.defer(new Callable<ObservableSource<? extends JSONObject>>() {
        @Override
        public ObservableSource<? extends JSONObject> call() throws Exception {
            return Observable.just(fetchModules());
        }
    });

在MainActivity中

moduleObservable
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new io.reactivex.Observer<JSONObject>() {
                @Override
                public void onSubscribe(Disposable d) {

                }

                @Override
                public void onNext(JSONObject response) {
                    // Your response is here
                }

                @Override
                public void onError(Throwable e) {
                     showAlert(context, e.getMessage());
                }

                @Override
                public void onComplete() {

                }
            });

在我自己研究这个问题之后,你不能(在写作的那一刻)在主线程中做到这一点

我希望Volley能够在主线程中完成它,因为我需要阻止直到Volley完成响应。 这是不可能的,Volley上的同步请求必须在异步线程中,而不是在主线程中。

我所做的工作是,在Volley请求的onResponse方法中执行后续代码

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM