У меня огромное приложение с множеством вложенных действий, которое содержит фрагменты с большим количеством информации.
APP Logic :
- Активность со списком проектов
- Щелкните по названию проекта, чтобы начать другое действие с фрагментами с вкладками
- Один из этих фрагментов содержит список каналов
- Нажмите на ленту новостей, чтобы начать другую операцию с вкладками Фрагменты со всей информацией о новостях (здесь я создаю отчет в формате PDF с информацией о новостях)
Я пытаюсь сгенерировать отчет в формате PDF, и иногда получаю сбой с этой ошибкой:
A/art: art/runtime/gc/collector/mark_sweep.cc:413] Tried to mark 0xebadde09 not contained by any spaces
art/runtime/utils.cc:184] 12c00000-12ca5000 rw-p 00000000 00:01 33268 /dev/ashmem/dalvik-main
и много строк над ...
Последнее сообщение перед ошибкой:
compiler allocated 5MB to compile java.io.File ...
Кажется, проблема с памятью.
В первый раз я пытаюсь поставить асинхронную задачу, которая генерирует отчет в формате PDF, но иногда я получаю ту же ошибку, поэтому теперь я вызываю поток из другой операции, которая не содержит все данные, содержащиеся в последней операции, связанной с Проект выбран.
Проблема в том, что я вижу из Android Profiler, что использование памяти ниже, чем в первом подходе (запустить асинхронную задачу из Activity, которая содержит фрагменты со всей информацией о проекте), но не так лучше.
Есть что-то, что я могу сделать, чтобы избежать этого?
Что-то вроде резервирования памяти для задачи или перехвата сбоя и уведомления пользователя об этом (возможно, скажите ему очистить стек приложений перед продолжением)
Лучший способ справиться с этой ситуацией в нескольких словах:
Здесь AsyncTask, который вызывает метод, генерирующий отчет
private class AsyncTaskRunner extends AsyncTask<Void, String, File> {
private File pdfFile;
ProgressDialog progressDialog;
@Override
protected File doInBackground(Void... params) {
pdfGenerator = new PdfGenerator(currentObject, "Project", getApplicationContext());
try {
pdfFile = pdfGenerator.createPdf();
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "Something goes wrong with generated file, please try again!", Toast.LENGTH_LONG).show();
} catch (DocumentException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "Something goes wrong with generated file, please try again!", Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "Something goes wrong with generated file, please try again!", Toast.LENGTH_LONG).show();
}
return pdfFile;
}
@Override
protected void onPostExecute(File pdfFile) {
progressDialog.dismiss();
viewPdf(pdfFile);
}
@Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(ReportPdfActivity.this,
"Making PDF report...",
"Please wait for the PDF report");
}
}
PS: я пытаюсь finish()
последний Activity
перед вызовом ActivityReport, который управляет генерацией отчетов и памятью из ~ 60 МБ, до ~ 50 МБ, но проблема в том, что все Действия связаны с Проектом, поэтому, если я уничтожу активность, которая вызывает «генерировать отчет», я разорвал логическую цепочку, которая связывает все действия между ними, поэтому перед тем, как переписать логическое соединение активности и finish()
все из них при вызове другого Activity
с фрагментом, я хочу узнать лучшее решение за это.
Спасибо
РЕДАКТИРОВАТЬ Лучшее объяснение структуры приложения
Это приложение берет данные из веб-приложения Odoo 11 ERP.
Мы использовали для этого фреймворк, и он задумался.
Если пользователь вошел в систему, первое действие в главном представлении содержит список всех проектов (и ящик навигации для управления другими фрагментами, такими как настройки, профиль и другие элементы)
Из фрагмента проектов по onClickListner он открывает другую активность (с
фрагменты представления с вкладками), которые показывают различные типы данных, связанных с этим проектом, такие как IssueFragment, TaskFragment, FeedFragment.
Все эти фрагменты, показанные в верхнем меню с вкладками, содержат список связанных аргументов (проблема, задача и т. Д.).
Каждый элемент onClick вызывает простое действие, в котором отображаются подробные сведения о связанном элементе ... НО в списке каналов открывается другое действие с (опять же) верхним меню с вкладками для навигации по различным фрагментам (поскольку в канале могут быть вопросы, проблемы, задачи, подписи и т. Д. И т. Д.) ....
Итак, последняя ситуация такова, что
- Активность с навигационным блоком и соответствующими фрагментами
---- (Project Fragment onClick) Активность с фрагментами с вкладками ( Документы Android )
------ (FeedFragment onClick) Упражнение с деталями ленты, распределенными по разным фрагментам
Скобка (... onClick) означает onClick в последнем действии / фрагменте
РЕДАКТИРОВАТЬ 2
Изменен AsyncTask с темой
PDFGenerator.java
public PdfGenerator(Integer currentObject, String objectType, Context context, Handler handler) {
this.currentObject = currentObject;
this.objectType = objectType;
this.context = context;
this.mHandler = handler;
//OTHER STUFFS....
}
/**
* Update UI according to the current state of PDF Creation
*/
private synchronized void showDialogHandler() {
// Give the new state to the Handler so the UI Activity can update
mHandler.obtainMessage(Constants.SHOW_DIALOG, 1).sendToTarget();
}
private synchronized void dismissDialogHandler() {
// Give the new state to the Handler so the UI Activity can update
mHandler.obtainMessage(Constants.SHOW_DIALOG, 1).sendToTarget();
}
public synchronized void startPdfCreation() {
Log.d(TAG, "Start PDF CREATION ");
simplePdfThread = null;
snaggingPdfThread = null;
// Start the thread to connect with the given device
simplePdfThread = new PdfSimpleThread();
simplePdfThread.start();
// show dialog
showDialogHandler();
}
public synchronized void startPdfSnaggingCreation() {
Log.d(TAG, "Start PDF SNAGGING CREATION ");
snaggingPdfThread = null;
simplePdfThread = null;
// Start the thread to connect with the given device
snaggingPdfThread = new PdfSnaggingThread();
snaggingPdfThread.start();
// show dialog
showDialogHandler();
}
private class PdfSimpleThread extends Thread {
File pdf;
public PdfSimpleThread() {
pdf = null;
}
public void run() {
try {
pdf = createPdf();
mHandler.obtainMessage(Constants.PDF_DONE, pdf).sendToTarget();
} catch (IOException | DocumentException e) {
e.printStackTrace();
}
}
}
private class PdfSnaggingThread extends Thread {
File pdf;
public PdfSnaggingThread() {
pdf = null;
}
public void run() {
try {
pdf = createSnaggingListPdf();
mHandler.obtainMessage(Constants.PDF_DONE, pdf).sendToTarget();
} catch (IOException | DocumentException e) {
e.printStackTrace();
}
}
}
private File createPdf() throws IOException, DocumentException {
//ALL THE STUFF HERE.... (it's over than 100 code lines)
}
private File createSnaggingListPdf() //...... it's same
И обработчик из вызывающего абонента. Активность:
@SuppressLint("HandlerLeak")
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case Constants.PDF_MESSAGE:
Toast.makeText(ActivityFeedDetails.this, "Generating PDF...",
Toast.LENGTH_SHORT).show();
break;
case Constants.SHOW_DIALOG:
int sentInt = (int) msg.obj;
if (sentInt == 1){
progressDialog = ProgressDialog.show(ActivityFeedDetails.this,
"Making PDF report...",
"Please wait for the PDF report");
} else {
progressDialog.dismiss();
}
break;
case Constants.PDF_DONE:
progressDialog.dismiss();
pdfGenerator = null;
pdfFile = (File) msg.obj;
viewPdf(pdfFile);
break;
}
}
};
Это улучшит производительность ... и создаст отчет в формате PDF, если я закрою приложение или действие тоже (AsyncTask этого не делает).
И я улучшаю методы, которые генерируют pdf, потому что я вижу, что предварительно загружаю все List<ODataRow>
перед началом создания (и теперь я вызываю их только тогда, когда мне нужно, поэтому я могу очистить другой с помощью .clear();
) ...
ODataRow
это класс, который реализует Serializable