我想连接到一个 Api,它根据我作为 GET 请求输入的内容返回 JSON 值。此 JSON 结构始终完全相同,只是这些属性的值不同。然后将所有这些 JSON 值构建到一个对象列表中,并从那里进一步为应用程序提供用户。
在帮助下,我现在有了一个工作代码,它连接并读取 HttpEntity
的 JSON
值,并将它们存储在 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/