Android - дождитесь ответа залпа, чтобы вернуться

Мне нужно выполнить запрос Volley и дождаться ответа, чтобы проанализировать его и вернуть, но я понятия не имею, как этого добиться. Кто-нибудь может помочь?

То, что у меня есть сейчас, это:

public String getLink() {
    JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {

            @Override
            public void onResponse(JSONObject response) {
                shortenURL = response.getString("url");
            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                // TODO Auto-generated method stub

           }
    });

    queue.add(jsObjRequest);

    return shortenURL;
}

person JorgeR    schedule 23.05.2014    source источник


Ответы (4)


Решение для многократного использования фабричного шаблона проектирования:

Чтобы вернуть или получить ответ Volley от другого метода, вам нужно написать функцию обратного вызова, что легко сделать с помощью интерфейсов.

Это простое решение взято из моей архитектуры MVC для приложений Android, разработанной с полной концепцией повторного использования и разделения ответственности.

Предположим, что JSONObject - это ваш ответ с сервера

Шаг 1)

Создайте Интерфейс Обратный вызов сервера

package xx.xx.xx.utils;

    import org.json.JSONObject;

    public interface ServerCallback{
        void onSuccess(JSONObject result);
    }

Шаг 2) Предположим, что ваш метод Запрос сервера Volley находится в Контроллере или в любом другом общем «контекстном» классе, сделайте это в своей любой Деятельности.

Controller controller = new Controller();
controller.youFunctionForVolleyRequest(email, password, this, loginUrl, new ServerCallback() {
                    @Override
                    public void onSuccess(JSONObject response) {
                       // do stuff here 
                    }
                  }
               );

3) В вашем классе контроллера вызовите функцию ServerCallback в inResponse(), которая будет выполнять ваш код в Activity только при ответе от сервера — миссия выполнена!

 public void youFunctionForVolleyRequest(final String email , final String password ,final Context context , final String URL, final ServerCallback callback)
    {
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("email", email);
        params.put("password", password);

        Log.e("sending json",params.toString());
        JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.POST,
                URL, new JSONObject(params), new Response.Listener<JSONObject>()
        {

            @Override
            public void onResponse(JSONObject response) {
               callback.onSuccess(response); // call call back function here

            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                //VolleyLog.d("Volley error json object ", "Error: " + error.getMessage());

            }
        }){
            @Override
            public String getBodyContentType()
            {
                return "application/json";
            }
        };

        // Adding request to request queue
        AppController.getInstance().addToRequestQueue(jsonObjReq);

    }
person Divyanshu Jimmy    schedule 19.01.2016
comment
как насчет объекта контроллера. они автоматически уничтожаются? или есть шанс для сборки мусора, если во время потока приложения создается так много объектов - person Rajesh Nasit; 06.05.2017
comment
@rajesh Если я прав, в вашей реализации очень мало сетевых вызовов. Для таких приложений, как электронная коммерция, на одной странице у вас будет 5-10. Различные источники сетевых вызовов. Несоблюдение фабричного шаблона может привести к огромной избыточности кода в нескольких действиях. gc будет выполняться для нестатических объектов класса Controller. - person Divyanshu Jimmy; 07.05.2017

Вероятно, вам не следует возвращать ссылку в свой метод.

Volley выполняет асинхронные задачи, это означает, что вы не можете знать, когда придет ответ от вашего веб-сервиса, это может быть 10 секунд или 10 минут.

Если вам нужна строка в вашей функции, вам, вероятно, следует создать метод и вызывать его, когда у вас есть результат.

Вот пример:

Я думаю, это то, что у вас есть

public void getTheLinkAndCallDoSomething(){
    String link = getLink();
    doSomethingWithTheLink(link);
}

Это будет работать, если getLink() отвечает синхронно. Залп не в данном случае.

И вот что вы можете сделать с Volley:

public void getTheLinkAndCallDoSomething(){
     JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET, 
                               url, null, new Response.Listener<JSONObject>() {

                    @Override
                    public void onResponse(JSONObject response) {
                        shortenURL = response.getString("url");
                        doSomethingWithTheLink(shortenURL);
                    }
                }, new Response.ErrorListener() {

                    @Override
                    public void onErrorResponse(VolleyError error) {
                        // TODO Auto-generated method stub

                    }
                });

    queue.add(jsObjRequest);
}

В этом случае вы звоните в WS, чтобы получить свой URL-адрес. И как только известен результат, вы звоните doSomethingWithTheLink()

В любом случае, если вы действительно хотите быть синхронным, вы можете посмотреть этот пост: Дождитесь результата запроса асинхронного залпа и верните его

Кроме того, имейте в виду, что ожидание ответа может привести к зависанию пользовательского интерфейса вашего приложения, и я думаю, это не то, что вам нужно.

person Quentin Klein    schedule 23.05.2014
comment
Инверсия логики. Большое спасибо :D - person Kadaj; 26.03.2017

вы не можете вернуть данные в свой метод getLink(). Используйте свой код как

String shortenURL  = ""; // activity global variable



public void getLink() {
        JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {

                    @Override
                    public void onResponse(JSONObject response) {
                        shortenURL = response.getString("url");
                    }
                }, new Response.ErrorListener() {

                    @Override
                    public void onErrorResponse(VolleyError error) {
                        // TODO Auto-generated method stub

                    }
                });

                queue.add(jsObjRequest);

}

Вы также можете увидеть больше информации на http://arnab.ch/blog/2013/08/asynchronous-http-requests-in-android-using-volley/

person Giru Bhai    schedule 23.05.2014

Вы можете сделать это, используя концепцию будущего

 RequestFuture<JSONObject> jsonObjectRequestFuture = RequestFuture.newFuture();
    JsonObjectRequest request = new JsonObjectRequest(ServiceUrl.BFF_BASE_URL + path, (JSONObject) postBody, jsonObjectRequestFuture, jsonObjectRequestFuture);
requestQueue.add(request);
JSONObject jsonObject = jsonObjectRequestFuture.get(30, TimeUnit.SECONDS);
person Prasanth Perumal    schedule 27.08.2019