2016-04-25 63 views
3

我解析了幾個Json鏈接,並嘗試將所有輸出添加到一個List。但是,該列表總是被改爲覆蓋,只包括一個鏈接的結果:將多個HTTP請求的結果彙總到單個列表

public class GetShopifyJsonData extends GetRawData { 
    private String LOG_TAG = GetShopifyJsonData.class.getSimpleName(); 
    private List<Product> mProduct; 
    private Uri mDestination; 

    public GetShopifyJsonData(int page) { 
     super(null); 
     createUri(page); 
     mProduct = new ArrayList<Product>(); 
    } 

    public void execute(){ 
     super.setRawUrl(mDestination.toString()); 
     DownloadShopifyData downloadShopifyData = new DownloadShopifyData(); 
     Log.v(LOG_TAG, "Built URI = " + mDestination.toString()); 
     downloadShopifyData.execute(mDestination.toString()); 
    } 

    public boolean createUri(int page) { 
     final String SHOPIFY_BASE_URL = ""; 
     final String SHOPIFY_PAGE_PARAM = "page"; 

     mDestination = Uri.parse(SHOPIFY_BASE_URL).buildUpon() 
       .appendQueryParameter(SHOPIFY_PAGE_PARAM, String.valueOf(page)).build(); 

     return mDestination != null; 
    } 

    public void processResults() { 

     if(getDownloadStatus() != DownloadStatus.OK){ 
      Log.e(LOG_TAG, "Error Downloading Raw Data"); 
      return; 
     } 

     final String SH_PRODUCTS = "products"; 
     final String SH_TYPE = "product_type"; 
     final String SH_VARIANTS = "variants"; 
     final String SH_TITLE = "title"; 
     final String SH_PRICE = "price"; 
     final String SH_GRAMS = "grams"; 

     try { 
      JSONObject jsonData = new JSONObject(getData()); 
      JSONArray productsArray = jsonData.getJSONArray(SH_PRODUCTS); 
      for (int i=0; i<productsArray.length(); i++) { 
       JSONObject jsonProduct = productsArray.getJSONObject(i); 
       String productType =jsonProduct.getString(SH_TYPE); 
       String title = jsonProduct.getString(SH_TITLE); 

       JSONArray variantsArray = jsonProduct.getJSONArray(SH_VARIANTS); 
       JSONObject variantProduct = variantsArray.getJSONObject(0); 
       String variantTitle = variantProduct.getString(SH_TITLE); 
       double price = variantProduct.getDouble(SH_PRICE); 
       int grams = variantProduct.getInt(SH_GRAMS); 

       if (productType.equals("Keyboard") || productType.equals("Computer")) { 
        Product productObject = new Product(title, price, grams, productType, variantTitle); 
        this.mProduct.add(productObject); 
       } 
      } 

      for(Product singleProduct : mProduct){ 
       Log.v(LOG_TAG, singleProduct.toString()); 
       Log.v(LOG_TAG, String.valueOf(mProduct.size())); 
      } 
     } catch (JSONException jsone) { 

      jsone.printStackTrace(); 
      Log.e(LOG_TAG, "Error Processing JSON data"); 
     } 
    } 
} 

而且從MainActivity電話:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    for (int i=1; i<6; i++) { 
     GetShopifyJsonData jsonData = new GetShopifyJsonData(i); 
     jsonData.execute(); 
    } 
} 

什麼我需要改變,以獲得產品中添加彼此在一個單一的列表?

+0

你認爲他們在哪裏被「覆蓋」? – shmosel

+0

@shmosel'Log.v(LOG_TAG,String.valueOf(mProduct.size()));' –

回答

1

每個GetShopifyJsonData都有自己List<Product>,你需要通過讓MainActivity聚集他們作爲完整的請求所有的產品或聚合那些既具有單GetShopifyJsonData實例請求。這種方法實現後者。

將一個回調接口添加到GetShopifyJsonData並需要它的一個實例作爲構造函數中的一個參數。我只在下面的代碼中包含更改。其他一切都是一樣的。

public class GetShopifyJsonData extends GetRawData { 
    public interface OnResultsReadyListener { 
     void onResultsReady(List<Product> products); 
    } 

    private OnResultsReadyListener mResultsListener; 

    public GetShopifyJsonData(int page, OnResultsReadyListener resultsListener) { 
     super(null); 
     createUri(page); 
     mProduct = new ArrayList<Product>(); 
     mResultsListener = resultsListener; 
    } 

    public void processResults() { 
     // Add this to the end of the method 
     if(mResultsListener != null) { 
      mResultsListener.onResultsReady(mProduct); 
     } 
    } 
} 

,然後更新MainActivity實現這個新的接口和結果添加到其列表作爲完整的請求。

public class MainActivity extends Activity 
     implements GetShopifyJsonData.OnResultsReadyListener { 
    private List<Product> allproducts; 

    @Override 
    void onResultsReady(List<Product> products) { 
     // allProducts contains products for all requests that have completed so far 
     allProducts.addAll(products); 
     Log.v(LOG_TAG, allProducts.size() + " total products downloaded."); 
    } 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     allProducts = new ArrayList<>(); 

     for (int i=1; i<6; i++) { 
      GetShopifyJsonData jsonData = new GetShopifyJsonData(i, this); 
      jsonData.execute(); 
     } 
    } 
} 
+0

令人驚歎,作品像一個魅力:) –

+0

很高興聽到我能夠幫助:) –

5

每次迭代該循環時都覆蓋jsonData,而不將每個以前的循環的結果存儲在別處。

for (int i=1; i<6; i++) { 
    GetShopifyJsonData jsonData = new GetShopifyJsonData(i); // throws out results of previous iteration and creates a new List each time 
    jsonData.execute(); 
} 

你應該保持一個List這個循環,你可以將所有的結果添加到每次迭代後外:

ArrayList<Product> allProducts = new ArrayList<Product>(); 
for (int i=1; i<6; i++) { 
    GetShopifyJsonData jsonData = new GetShopifyJsonData(i); 
    jsonData.execute(); 
    allProducts.addAll(jsonData.getProducts()) // add a method that gets all of the products from each iteration 
} 

編輯:

既然你使用線程來收集JSON數據,您可以使用一個列表GetShopifyJsonData對象來維護對這些線程的引用;

ArrayList<GetShopifyJsonData> allJSONData = new ArrayList<GetShopifyJsonData>(); 
for (int i=1; i<6; i++) { 
    allJSONData.add(new GetShopifyJsonData(i)); 
    allJSONData.get(i).execute(); // executes each task as discrete instances 
} 

從那裏您可以檢查線程的狀態,並在完成時從列表中檢索JSON數據。下面是一個不是非常好的例子,爲了說明的緣故:

ArrayList<Product> allProducts = new ArrayList<Product>(); 
for (int i=1; i<6; i++) { 
    while(!allJSONData.get(i).isComplete()){ // add a method that checks if a task has been completed 
     //this is a busy wait, don't do this! 
    } 
    allProducts.addAll(jsonData.get(i).getProducts()) // add a method that gets all of the products from each iteration 
} 

現在,我不是一個機器人專家,而是一個快速掠過文檔的AsyncTask向我表明onPostExecute(Result)getStatus()很可能是有益的。如果我是正確的,我希望你實際上可以將JSON數據添加到onPostExecute()的列表中,並通過將主列表傳遞到​​來完全跳過使用ArrayList<GetShopifyJsonData>;沿線的東西:

ArrayList<Product> allProducts = new ArrayList<Product>(); 
for (int i=1; i<6; i++) { 
    GetShopifyJsonData jsonData = new GetShopifyJsonData(i); 
    jsonData.execute(allProducts); // pass the reference to your list in execute() 
} 

// in your AsyncTask class: 
private ArrayList<Product> products; // private List instance 

execute(ArrayList<Product> allProducts){ 
    products = allProducts; 
    // do other logic 
    ... 
} 

onPostExecute(List<Product> dataFromJSON){ 
    products.addAll(dataFromJSON); // add the results to the instance variable, which also updates the master list 
} 

雖然這是一個過於簡單化。您必須確保線程不會同時添加到列表中,因爲如果允許這樣做,可能會發生壞事。文檔說在UI線程上運行,但我不知道這意味着什麼。

+1

我相信你是在正確的軌道上的問題,但我懷疑這將解決它作爲'execute()'是可能的發生在後臺線程上,當您嘗試將'jsonData.getProducts()'添加到'allProducts'時,'processResults()'不會完成。 –

+0

這當然是可能的,這樣做是有道理的。但是,從問題中可以得到的結果來看,我們無法確定是否涉及某些線程。如果OP澄清,否則我會更新我的答案。 – NAMS

+1

有線程涉及,我正在使用AsyncTask來解析Json鏈接 –