优化JSON解析 - 获取与ID关联的名称

时间:2014-04-25 01:48:31

标签: android json

为了概述我正在努力实现的目标,我试图尽可能少地访问服务器以提高效率。我以为我用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;
        }
    }

1 个答案:

答案 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;
    }