我想连接到Api,它根据我输入的GET请求返回JSON值。此JSON结构始终完全相同,只有这些属性的值不同。然后将所有这些JSON值构造成一个对象列表,然后在应用程序中进一步使用该用户。
在帮助下,我现在有一个工作代码,用JSON
连接并读取HttpEntity
值并将其存储在new JSONObject
中。此对象被发送到另一个函数,其中对象被剥离,然后constructed
发送到Object list
以供以后在应用程序中使用。
此代码正常工作。除了此Api链接仅显示50个结果,具体取决于输入的GET
请求。如果结果超过50个,则会创建一个新页面,该页面可以通过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);
}
}
在onPostExecute
类的AsyncFetch
中,对象随后会发送回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;
}
答案 0 :(得分:0)
好吧,我不认为你想要做的事情是个好主意,因为如果服务器数据量太大,你可以OutOfMemoryError
。
否则,这是我建议加载所有数据:
1)制作两个类变量(在你的活动中),第一个是页数,第二个是你的计数器:
private static final int PAGES_NUMBER = 38; // i think last page is 38 in your api
private int mPagesCounter = 0;
2)添加JSONObject作为类变量(在您的活动中)以保存您的页面:
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();
}
}
答案 1 :(得分:0)
AsyncTask
是一个很好的工具,当您尝试异步执行单个任务时。
您正在尝试做的事情似乎是ThreadPool
的工作,{{1}}是一个旨在使用一定数量的工作线程(或执行程序)处理任务队列的工具。您可以使每个任务将下一个任务添加到队列中,或者立即对整个批处理进行排队。
这是一种非常强大的模式。
官方example here(示例分为几页,导航位于底部)。