0

我需要下载一个大的 json 字符串。我为此使用aQuery。然后我需要在对象列表(10k +)中解析这个字符串(我为此使用 Gson 库)并将这个列表插入数据库(使用 GreenDAO 创建)。但在插入之前,我需要按我的对象字符串字段对该列表进行排序。我正在使用 Collat​​or 类进行排序,因为该文件可能使用不同的语言。问题是:如何使用尽可能少的内存来做这样的事情?

现在我下载一个字符串(+String,我也尝试过使用 Streams)然后解析它(+List)然后对其进行排序(更多对象)。我在一个单独的线程中做它,但即使它完成了内存也没有释放。我认为如果我可以在数据已经在数据库中时对数据进行排序(而不是在选择它时,它会很慢),那么这可以解决,但我不知道如何。

这是一些代码。这是从文件加载数据。从文件加载时内存也存在同样的问题,我使用 InputStream 而不是将 JSON 字符串放入内存。

public static void getEnciclopediaDataFromFile() {
    mRequestStates.put("enc", true);

    try {
        EncyclopediaParser parser = new EncyclopediaParser(ResourceManager.getResourceManager().loadFile("enc_data"),
                                                           ResourceManager.getResourceManager().loadFile("enc_data"),
                                                           1361531132);
        parser.start();
    } catch (Exception e) {
        mRequestStates.put("enc", false);
        EventBus.getDefault().post(EVENT_ENCYCLOPEDIA_DOWNLOAD_COMPLETE);
    }
}

这是解析器线程。有两个构造函数 - 一个用于从 Web 加载(字符串参数),另一个用于从文件加载(InputStream 参数)。

    private static class EncyclopediaParser extends Thread {
    // -----------------------------------------------------------------------
    //
    // Fields
    //
    // -----------------------------------------------------------------------
    private String mJsonData;
    private Reader mTitlesReader;
    private Reader mContentReader;
    private long mUpdateTime;

    // -----------------------------------------------------------------------
    //
    // Constructor
    //
    // -----------------------------------------------------------------------
    public EncyclopediaParser(String jsonData, long updateTime) {
        mJsonData = jsonData;
        mUpdateTime = updateTime;
        this.setPriority(Thread.NORM_PRIORITY - 1);
    }

    public EncyclopediaParser(Reader titlesReader, Reader contentReader, long updateTime) {
        mTitlesReader = titlesReader;
        mContentReader = contentReader;
        mUpdateTime = updateTime;
        this.setPriority(Thread.NORM_PRIORITY - 1);
    }

    // -----------------------------------------------------------------------
    //
    // Methods
    //
    // -----------------------------------------------------------------------
    @Override
    public void run() {
        Type type;

        try {
            List<ArticleContent> content = null;
            type = new TypeToken<Collection<ArticleContent>>(){}.getType();
            if(mContentReader == null)
                content = new Gson().fromJson(mJsonData, type);
            else
                content = new Gson().fromJson(mContentReader, type);

            List<ArticleTitle> titles = null;
            type = new TypeToken<Collection<ArticleTitle>>(){}.getType();
            if(mTitlesReader == null)
                titles = new Gson().fromJson(mJsonData, type);
            else
                titles = new Gson().fromJson(mTitlesReader, type);

            for(ArticleTitle title : titles)
                title.setTitle(title.getTitle().trim());

            TitlesComparator titlesComparator = new TitlesComparator();
            Collections.sort(titles, titlesComparator);
            for(int i = 0; i < titles.size(); ++i)   //sorting enc data
                titles.get(i).setOrderValue((long)i);

            //create sections data
            Collator collator = Collator.getInstance(Locale.GERMAN);
            collator.setStrength(Collator.PRIMARY);
            ArrayList<String> sectionNamesList = new ArrayList<String>();
            ArrayList<Integer> sectionIndexesList = new ArrayList<Integer>();
            String prevLetter = "";
            for (int i = 0; i < titles.size(); ++i) {
                if(titles.get(i).getTitle().length() > 0){
                    if(!Character.isLetter(titles.get(i).getTitle().charAt(0))) {
                        if( !sectionNamesList.contains("#")) {
                            sectionNamesList.add("#");
                            sectionIndexesList.add(i);
                        }
                    }
                    else if(collator.compare(titles.get(i).getTitle().substring(0, 1), prevLetter) > 0) {
                        sectionNamesList.add(titles.get(i).getTitle().substring(0, 1).toUpperCase(Locale.GERMAN));
                        sectionIndexesList.add(i);
                    }
                    prevLetter = titles.get(i).getTitle().substring(0, 1);
                }
            }
            String[] sectionNames = new String[sectionNamesList.size()]; //use lists instead
            Integer[] sectionIndexes = new Integer[sectionIndexesList.size()];
            sectionNamesList.toArray(sectionNames);
            sectionIndexesList.toArray(sectionIndexes);
            AppData.setSectionIndexes(Utils.convertIntegers(sectionIndexes));
            AppData.setSectionNames(sectionNames);

            GreenDAO.getGreenDAO().insertArticles(titles, content);
            AppData.setEncyclopediaUpdateTime(mUpdateTime);
            mRequestStates.put("enc", false);
            if(mTitlesReader != null)
                mTitlesReader.close();
            if(mContentReader != null)
                mContentReader.close();
        } catch (Exception e) {
            Log.e("Server", e.toString());
        } finally {
            EventBus.getDefault().post(EVENT_ENCYCLOPEDIA_DOWNLOAD_COMPLETE);
        }
    }
}

所有 GreenDAO 对象都是静态的。解析仅在第一次启动(从文件)和通过“更新”按钮单击(从网络)时完成。我注意到,即使我在初始(从文件)解析完成后重新启动我的应用程序,它也会使用与第一次完成解析后一样多的内存。

4

0 回答 0