Почему ical4j так долго строится?
Я пытаюсь проанализировать файл Google Календарь ical (.ics), используя ical4j в Android. Но создание календаря из входного потока занимает более 40 секунд.
calendar = builder.build(fis);
Размер файла составляет всего 150 КБ. Кроме того, когда я использую тот же код и запускаю его на ПК, создание календаря происходит менее чем за секунду. Я также заметил огромное количество сбора мусора в LogCat. Может кто-нибудь мне помочь?
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView = (TextView)findViewById(R.id.Hello_World);
new Download().execute();
}
final class Download extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute(){
TextView.setText("Downloading");
}
@Override
protected Void doInBackground(Void... arg0) {
try {
URL url = new URL(URL);
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.connect();
FileOutputStream fos = openFileOutput(fileName, MainActivity.MODE_PRIVATE);
InputStream is = c.getInputStream();
byte[] buffer = new byte[1024];
int length = 0;
while ((length = is.read(buffer)) != -1) {
fos.write(buffer, 0, length);
}
fos.close();
is.close();
} catch (IOException e) {
Log.d("log_tag", "Error: " + e);
}
return null;
}
@Override
protected void onPostExecute(Void Result) {
TextView.setText("Saved...Loading Data");
new Loadicaldata().execute();
}
}
final class Loadicaldata extends AsyncTask<Void, Void, Void> {
String Summary = null;
@Override
protected Void doInBackground(Void... arg0) {
FileInputStream fis = null;
try {
fis = openFileInput(fileName);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_UNFOLDING, true);
CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION, true);
CalendarBuilder builder = new CalendarBuilder();
Calendar calendar = null;
try {
calendar = builder.build(fis);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
b.append(calendar.getProperty("X-WR-CALNAME").getValue());
ComponentList events = calendar.getComponents(Component.VEVENT);
VEvent Event = (VEvent) events.get(0);
Summary = Event.getDescription().getValue();
/*
for (Object event : calendar.getComponents(Component.VEVENT)) {
if (((VEvent) event).getSummary() != null) {
b.append("\n\n");
b.append(((VEvent) event).getSummary().getValue());
b.append(": ");
b.append(((VEvent) event).getStartDate().getDate());
}
}
*/
return null;
}
@Override
protected void onPostExecute(Void Result) {
TextView.setText(Summary);
}
}
LogCat: http://dl.dropbox.com/u/35866688/LogCat.txt
Кроме того, я могу смело исключить возможность ошибки ввода-вывода, так как метод Calendar.load также занимает много времени.
Это файл, если кому-то интересно. https://www.google.com/calendar/ical/m0es4hhj4g9d69ibak88tvoup0%40group.calendar.google.com/public/basic.ics
1 ответ
Одна возможность состоит в том, что вы читаете из небуферизованного входного потока в doInBackground
метод. Если CalendarBuilder.build(...)
Метод читает по одному байту за раз, это вызовет много системных вызовов и значительно замедлит работу.
Вторая возможность заключается в том, что проблема вызвана сборкой мусора. С этим ничего не поделаешь, но увеличение размера кучи может помочь. (Одной из причин чрезмерных издержек GC является работа с кучей, близкой к полной. Эффективность GC сильно снижается, если они не могут восстановить много памяти в каждом цикле GC...)