将多个HTTP请求的结果汇总到单个列表
我解析了几个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();
}
}
什么我需要改变,以获得产品中添加彼此在一个单一的列表?
每个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();
}
}
}
令人惊叹,作品像一个魅力:) –
很高兴听到我能够帮助:) –
每次迭代该循环时都覆盖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线程上运行,但我不知道这意味着什么。
我相信你是在正确的轨道上的问题,但我怀疑这将解决它作为'execute()'是可能的发生在后台线程上,当您尝试将'jsonData.getProducts()'添加到'allProducts'时,'processResults()'不会完成。 –
这当然是可能的,这样做是有道理的。但是,从问题中可以得到的结果来看,我们无法确定是否涉及某些线程。如果OP澄清,否则我会更新我的答案。 – NAMS
有线程涉及,我正在使用AsyncTask来解析Json链接 –
你认为他们在哪里被“覆盖”? – shmosel
@shmosel'Log.v(LOG_TAG,String.valueOf(mProduct.size()));' –