我需要下载一个大的json String。我正在使用aQuery。然后我需要在一个对象列表中解析这个字符串(10k +)(我正在使用Gson库)并将此列表插入数据库(使用GreenDAO创建)。但在插入之前,我需要通过我的对象字符串字段对此列表进行排序。我正在使用Collator类进行排序,因为这个文件可能使用不同的语言。问题是:如何使用尽可能少的内存来做这样的事情?
现在我下载一个String(+ 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 param)。
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对象都是静态的。解析仅在第一次启动(从文件)和“更新”按钮单击(从Web)完成。我注意到,即使我在初始(从文件)解析完成后重新启动我的应用程序,它将使用尽可能多的内存,因为它是第一次完成解析后。