为了概述我正在努力实现的目标,我试图尽可能少地访问服务器以提高效率。我以为我用if-elseif-else块来处理这件事,但它仍然需要比我想要的更长的时间。有什么办法可以改善吗?目前的形式,通过这一部分需要2分钟。我显然希望它尽可能快。
当从JSON中专门返回runeId编号时,它是即时的。但是,我需要做的是检索与该ID相关联的名称并返回该名称。我已经对代码部分进行了跟踪查看,并将其包含在下面。我不确定如何阅读它,但我确定故障部分是我从id(getRuneInfo)获取名称的方法。
最终,我想要做的是将这些信息本地存储在设备上,这样,随着时间的推移,它不必访问服务器,因为id-name对将存储在本地,但我我不确定如何做到这一点。
Traceview文件: https://www.dropbox.com/s/4fc6kdk35wackwr/RuneLoop.trace
循环:
// Loop through pages, page names stored in string array
for (int i = 0; i < rune.length(); i++) {
JSONObject c = rune.getJSONObject(i);
JSONArray slots = c.getJSONArray(TAG_SLOTS);
name[i] = c.getString(TAG_NAME);
// This loop is where the slowdown is. Before I added this
// the code ran very quickly.
for (int x = 0; x < 27; x++) {
JSONObject s = slots.getJSONObject(x);
if (Integer.valueOf(s.getString(TAG_RUNEID)).equals(prevId)) {
runesArray[i][x] = runesArray[i][x - 1];
prevId = Integer.valueOf(s.getString(TAG_RUNEID));
} else if (Integer.valueOf(s.getString(TAG_RUNEID)).equals(runeIdArray[Integer.valueOf(s.getString(TAG_RUNEID))]))
runesArray[i][x] = runeIdArray[Integer.valueOf(s.getString(TAG_RUNEID))];
else
// I believe the slowdown stems specifically from this
runesArray[i][x] = getStaticData.getRuneInfo(s.getString(TAG_RUNEID));
runeIdArray[Integer.valueOf(s.getString(TAG_RUNEID))] = runesArray[i][x];
}
getRuneInfo方法:
public String getRuneInfo(String runeId) {
String name = null;
try {
name = new GetRunes()
.execute(runeId)
.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return name;
}
else语句调用getRuneInfo,它启动它。我相信所有的提取都会减慢它的速度。 GetRunes:
public static class GetRunes extends AsyncTask<String, String, String> {
protected String doInBackground(String[] runeId) {
String url = "https://prod.api.pvp.net/api/lol/static-data/" + region + "/v1.2/rune/" + runeId[0] + "?api_key=" + api_key;
JSONParser jsonParser = new JSONParser();
JSONObject runeInfo = jsonParser.getJSONFromUrl(url);
String name = null;
try {
name = runeInfo.getString("name");
} catch (JSONException e) {
e.printStackTrace();
}
return name;
}
}
答案 0 :(得分:1)
据我了解你在做什么,似乎有27个请求被发送到服务器,所以这显然需要时间。
请求可能是串行运行的,也就是说,一个请求会在另一个完成时启动。您可以通过启用并行执行来节省一些时间:
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR).
但是,并行执行的任务数量有限,并且您必须稍微调整代码以进行并行执行。我担心,如果你需要这27个请求,除此之外不能做太多。
关于第二个问题,显然您需要在本地存储请求。您可以做的最简单的事情是,在GetRunes
中,将每个收到的JSON保存到SD卡中的文件中,这非常简单,然后,在getRunes
中,检查是否已经下载了此类文件。这样,下载所有符文可能需要2分钟,但您只需要执行一次。一旦所有文件都存储在SD卡中,执行将几乎是即时的。
我在这里发布了一个例程,我用它来缓存内容,为你的灵感...基本上我用URL调用它,并将该URL下载到SD卡,并存储在文件名中,该文件名是url的md5哈希值。所以在下载之前,我只是检查所请求的URL的md5是否存在于缓存中,如果存在,我从sdcard读取文件而不是下载它。
private static boolean cache_url(Context context, String fileurl) throws DeviceNotOnlineException {
try {
File cacheDir=new File(context.getCacheDir(),"url_cache");
ensureOnline();
if(!cacheDir.exists())
cacheDir.mkdirs();
File f=new File(cacheDir, md5(fileurl));
URL url = new URL(fileurl);
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(f);
byte data[] = new byte[16384];
int count=0;
if (Conf.LOG_ON) Log.v(TAG, "Caching "+fileurl+" into "+f.getAbsolutePath());
while ((count = input.read(data)) != -1) {
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
return true;
} catch (FileNotFoundException f) {
if (Conf.LOG_ON) Log.e(TAG, "WARNING: FILE NOT FOUND! "+f.getMessage());
} catch (Exception e) {
if (Conf.LOG_ON) e.printStackTrace();
}
return false;
}