2017-01-19 6 views
0

Это метод для возврата пользовательского списка. Однако я обновляю список внутри задачи async (OnResponse). Мне пришлось использовать запрос вложенного залпа. Я объявил элемент списка, но не смог использовать его внутри метода OnRespose. Кто-нибудь может мне с этим помочь? Как я могу вернуть элемент списка из метода.Возвращаемый список из AsyncTask

private ArrayList<sItem> fetchApiData(){ 

    ArrayList<sItem> list= new ArrayList<>(); 
    String url="http://www.gadgetsinnepal.com.np/wp-json/wp/v2/posts/"; 

    JsonArrayRequest jsArrayRequest = new JsonArrayRequest 
      (Request.Method.GET, url, null, new Response.Listener<JSONArray>() { 

       @Override 
       public void onResponse(JSONArray response) { 


        try { 

         // Parsing json array response 
         // loop through each json object 

         for (int i = 0; i < response.length(); i++) { 
          sItem sitem=new sItem(); 

          JSONObject item = (JSONObject) response 
            .get(i); 
          String id = item.getString("id"); 
          sitem.id=id; 
          String date = item.getString("date"); 

          JSONObject titleobj = item 
            .getJSONObject("title"); 
          String title= titleobj.getString("rendered"); 
          sitem.title=title; 
          String featuredMedia= item.getString("featured_media"); 


          JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET, 
            "http://www.gadgetsinnepal.com/wp-json/wp/v2/media/"+featuredMedia, null, new Response.Listener<JSONObject>() { 

           @Override 
           public void onResponse(JSONObject nested_response) { 

            try { 
             JSONObject guilld = nested_response.getJSONObject("guid"); 
             String featured_img_url = guilld.getString("rendered"); 
             sitem.img=featured_img_url; 
             list.add(sitem); 
             //Toast.makeText(getApplicationContext(),"IMAGE :" + list.get(0),Toast.LENGTH_LONG).show(); 

            } catch (JSONException e) { 
             e.printStackTrace(); 
             Toast.makeText(getApplicationContext(), 
               "Error: " + e.getMessage(), 
               Toast.LENGTH_LONG).show(); 
            } 
           } 
          }, new Response.ErrorListener() { 

           @Override 
           public void onErrorResponse(VolleyError error) { 
            Toast.makeText(getApplicationContext(), 
              "ERROR "+error.getMessage(), Toast.LENGTH_LONG).show(); 
            if (error instanceof TimeoutError || error instanceof NoConnectionError) { 
             Toast.makeText(getApplicationContext(),"network timeout error", 
               Toast.LENGTH_LONG).show(); 
            } else if (error instanceof AuthFailureError) { 
             //TODO 
            } else if (error instanceof ServerError) { 
             //TODO 
            } else if (error instanceof NetworkError) { 
             //TODO 
            } else if (error instanceof ParseError) { 
             //TODO 
            } 
           } 
          }); 
          jsonObjReq.setRetryPolicy(new DefaultRetryPolicy(
            7000, 
            DefaultRetryPolicy.DEFAULT_MAX_RETRIES, 
            DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)); 

          MySingleton.getInstance(getApplicationContext()).addToRequestQueue(jsonObjReq); 


         } 
        } catch (JSONException e) { 
         e.printStackTrace(); 
         Toast.makeText(getApplicationContext(), 
           "Error: " + e.getMessage(), 
           Toast.LENGTH_LONG).show(); 
        } 
       } 
      }, new Response.ErrorListener() { 

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

       } 
      }); 

    MySingleton.getInstance(getApplicationContext()).addToRequestQueue(jsArrayRequest); 

    return list; 
} 

ответ

0

Чтобы использовать переменные замыкания внутри слушателя, необходимо отметить переменную окончательный при объявлении его. Это нормально для списка, поскольку окончательный список все еще можно манипулировать внутри (вы можете добавлять/удалять элементы из него).

final ArrayList<sItem> list = new ArrayList<>();

Однако, вы, вероятно, до сих пор не получите свой результат из-за асинхронного поведения. Функция main, wrapping немедленно возвращает список; даже до того, как Volley отпустит сетевые запросы. Он заполняется только позже ответом Volley в будущем.

Обращение к fetchApiData() (как написано сейчас) всегда будет возвращать пустой список. (Тем не менее, это ссылка, поэтому в зависимости от того, как вы ее используете, ее можно заполнить позже, но это плохая конструкция и почти всегда будет использоваться неправильно любым пользователем функции.)

Вместо этого вы должен, вероятно, предоставить интерфейс или функцию обратного вызова в список параметров fetchApiData(), а затем вызвать эту функцию после того, как вы закончите заполнение списка из сетевых ответов.

Примечание. Поскольку у вас есть вложенные вызовы, вам также нужно будет отслеживать, когда все вложенные вызовы закончены, и в каждом вложенном onResponse проверьте, чтобы, когда это последний звонок для ответа, он, наконец, начнет обратный вызов ,

Затем любые вызовы fetchApiData() с обратным вызовом будут знать, что при вызове этого обратного вызова, который будет заполнен полностью, список будет заполнен полностью.

+0

Если его не так много, чтобы спросить .. Как выглядит правильный дизайн? –

+0

@NipeshKc Это становится беспорядочным для реализации. Я бы предположил, что в качестве альтернативы вы посмотрите на Observables через RxJava/RxAndroid. Сделал бы все это намного проще, чтобы писать и понимать. (Как только вы перейдете к кривой обучения Observable и Rx). –

0

объявить список как окончательные, или в качестве глобального поля

 Смежные вопросы

  • Нет связанных вопросов^_^