2017-01-19 80 views
0

這是返回自定義列表的方法。不過,我正在更新異步任務(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,wraping函數立即返回列表;甚至在Volley啓動網絡請求之前。只有在稍後的某個時候Volley的迴應纔會填補它。

致電fetchApiData()(因爲它現在寫入)將始終返回空列表。 (但是,這是一個參考,因此取決於你如何使用它,它可能會在稍後填充,但這是糟糕的設計,並且幾乎總是會被任何功能的使用者錯誤地使用。)

而是,您可能應該爲fetchApiData()參數列表提供接口或回調函數,然後在完成從網絡響應填充列表後調用該函數。

注意:因爲您有嵌套調用,所以您還需要跟蹤所有嵌套調用何時完成,並在每個嵌套onResponse檢查中進行檢查,以便當它是最後一次響應時,它將最終啓動回調。

然後,無論調用帶回調的fetchApiData(),都會知道當它提供的回調被調用時,該列表將被完全填充。

+0

如果沒有太多問的話,那麼正確的設計會是什麼樣子? –

+0

@NipeshKc它實現起來很麻煩。實際上,我會建議您通過RxJava/RxAndroid替代您觀察Observables。會使整個事情變得更容易寫和理解。 (一旦你瞭解了Observable和Rx的學習曲線。) –

0

聲明您的列表作爲最終,還是作爲一個全球性的領域