java - 循环 AsyncTask 类并获取 Json 并将其作为对象存储在列表中

标签 java android json list object

我想连接到一个 Api,它根据我作为 GET 请求输入的内容返回 JSON 值。此 JSON 结构始终完全相同,只是这些属性的值不同。然后将所有这些 JSON 值构建到一个对象列表中,并从那里进一步为应用程序提供用户。

在帮助下,我现在有了一个工作代码,它连接并读取 HttpEntityJSON 值,并将它们存储在 new JSONObject 中。该对象被发送到另一个函数,在该函数中对象被剥离,然后构造对象列表中,供以后在应用程序中使用。

此代码有效。除了此 Api 链接仅显示 50 个结果,具体取决于作为 GET 请求输入的内容。当有超过 50 个结果时,将创建一个新页面,可以通过 url 末尾的数字访问该页面。所有这些可能存在的页面(不必作为用户搜索请求)也必须添加到对象列表中。

问题:如何使用新的 url 遍历扩展的 AsyncTask 类以从中获取 JSON 数据?

我再次注意到这段代码适用于单个页面,但我不知道如何遍历所有现有页面并将它们添加到同一对象列表。

我们从activity.java开始

String userSearchRequest = search_activity_data.getString("userSearchRequest");
String URL = "http://www.gw2spidy.com/api/v0.9/json/item-search/" + userSearchRequest + "/";
// example api url:
//http://www.gw2spidy.com/api/v0.9/json/item-search/Iron/0"
//The last number is the page you are viewing, every 50 results a new page is created. With 51 results there will be a page 0 and 1 to access.

AsyncFetch AsyncFetch = new AsyncFetch(this);
AsyncFetch.setOnResponse(this);
AsyncFetch.execute(URL);

从这里 URL 被传递到 AsyncFetch 类以作为参数运行 doInBackground

public class AsyncFetch extends AsyncTask<String, Void, JSONObject> {

    public AsyncFetch(Context context) {
        this.context = context;
    }

    private Context context;
    private JSONObject jsonObject;
    private onResponse onResponse;

    public void setOnResponse (onResponse onResponse) {
        this.onResponse = onResponse;
    }

    @Override
    protected JSONObject doInBackground(String... params ) { //Incompatible return type
        // TODO Auto-generated method stub

        try {
            HttpGet get = new HttpGet(params[0]);
            HttpClient client = new DefaultHttpClient();
            HttpResponse response = client.execute(get);
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity);
            jsonObject = new JSONObject(result);

        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return jsonObject;
    }

    @Override
    protected void onPostExecute(JSONObject result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        this.onResponse.onResponse(result);
    }

    public interface onResponse {
        public void onResponse(JSONObject object);
    }


}

AsyncFetch 类的 onPostExecute 中,然后将对象发送回 activity.java

public void onResponse(JSONObject object) {
        Log.i("gw2Log", object.toString());

        apiRootObject resultClass = new apiRootObject();

        try {
            resultClass.setCount(object.getInt("count"));
            resultClass.setPage(object.getInt("page"));
            resultClass.setLast_page(object.getInt("last_page"));
            resultClass.setTotal(object.getInt("total"));
            JSONArray list = new JSONArray(object.getString("results"));

            for (int i = 0; i < resultClass.getCount(); i++) {
                JSONObject resultsObject = list.getJSONObject(i);
                apiResults temp = new apiResults();
                temp.setData_id(resultsObject
                        .getInt("data_id"));
                temp.setName(resultsObject
                        .getString("name"));
                temp.setRarity(resultsObject
                        .getInt("rarity"));
                temp.setRestriction_level(resultsObject
                        .getInt("restriction_level"));
                temp.setImg(resultsObject
                        .getString("img"));
                temp.setType_id(resultsObject
                        .getInt("type_id"));
                temp.setSub_type_id(resultsObject
                        .getInt("sub_type_id"));
                temp.setPrice_last_changed(resultsObject
                        .getString("price_last_changed"));
                temp.setMax_offer_unit_price(resultsObject
                        .getInt("max_offer_unit_price"));
                temp.setMin_sale_unit_price(resultsObject
                        .getInt("min_sale_unit_price"));
                temp.setOffer_availability(resultsObject
                        .getInt("offer_availability"));
                temp.setSale_availability(resultsObject
                        .getInt("sale_availability"));
                temp.setSale_price_change_last_hour(resultsObject
                        .getInt("sale_price_change_last_hour"));
                temp.setOffer_price_change_last_hour(resultsObject
                        .getInt("offer_price_change_last_hour"));
                resultClass.addObject(temp);
            }

        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        for(int i = 0; i < resultClass.count; i++) {
            Log.i("gw2Log", resultClass.getObject(i).name);

        }

    }

现在我可以从这里访问 resultClass 列表并遍历所有对象并显示它们的属性和值。

我怎样才能使它适用于具有完全相同的 JSON 结构的多个页面?

编辑:我有这段代码可以在 C# 中运行。这是我的完全相同的项目,但现在在 Android java 中。所以目标完全相同,但我无法让它工作

public static RootObject objFromApi_idToName(string spidyApiUrl, int page){
            RootObject rootObject = null;
            RootObject tempRootObject = null;

            do{
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(spidyApiUrl + "/" + page);

                WebResponse response = request.GetResponse();
                using (Stream responseStream = response.GetResponseStream()){
                    StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
                    var jsonReader = new JsonTextReader(reader);
                    var serializer = new JsonSerializer();
                    tempRootObject = serializer.Deserialize<RootObject>(jsonReader);

                    if (rootObject == null){
                        rootObject = tempRootObject;
                    }
                    else{
                        rootObject.results.AddRange(tempRootObject.results);
                        rootObject.count += tempRootObject.count;
                    }
                }
                page++;
            }

            while (tempRootObject != null && tempRootObject.last_page != tempRootObject.page);
            return rootObject;
        }

最佳答案

好吧,我不认为你想做什么是个好主意,因为如果服务器数据量太大,你可能会遇到 OutOfMemoryError

否则,这是我加载所有数据的建议:

1) 创建两个类变量(在您的 Activity 中),第一个用于页数,第二个用于您的计数器:

private static final int PAGES_NUMBER = 38; // i think last page  is 38 in your api
private int mPagesCounter = 0;

2) 添加一个 JSONObject 作为类变量(在您的 Activity 中)以保存您的页面:

JSONObject mAllData = new JSONObject();

3) 将您的 onPostExecute() 更改为仅在所有页面都已加载时才调用 onResponse():

    @Override
        protected void onPostExecute(JSONObject result) {
            super.onPostExecute(result);

            mAllData.put("page"+mPagesCounter, result);// save your current page with "pageX" as key
            mPagesCounter++;

            if(mPagesCounter <= PAGES_NUMBER){// create another task to load next page
                 AsyncFetch AsyncFetch = new AsyncFetch(YourActivity.this);
                 AsyncFetch.setOnResponse(YourActivity.this);
                 AsyncFetch.execute(URL+mPagesCounter);
            } else {// all pages are loaded -> call onResponse() method 
                 this.onResponse.onResponse(mAllData);
            }
        }

4) 更改 onResponse() 方法以处理新的 json 格式。

要循环页面,您可以这样做:

    Iterator it = object.keys();
    while (it.hasNext()) {
        String key = (String)it.next();
        try {
            JSONObject jsonPage = object.get(key);// here you get your page
            // do the rest of stuff with the page
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

关于java - 循环 AsyncTask 类并获取 Json 并将其作为对象存储在列表中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29856142/

相关文章:

javascript - 给出折线图的本地 json 文件

json - 如何在 Swift 中解码 HTML 实体?

android - 从 OnItemClickListener 检索数据

Java仅通过一个对象发送类参数

java - 最适合重复元素的 Java Collection

android - 如何为每个单元测试获取我的应用程序类的新实例?

android - 发布企业 Android/iOS 应用程序的最佳实践

java - 找不到 MPAndroidChart 错误类 ValueFormatter

java - 如何通过java将参数传递给shell命令?

android - 是否可以用displayImage()设置ImageSize?