2016-04-25 92 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链接 –