Запрос памяти перед запуском AsyncTask и как им управлять - PullRequest
0 голосов
/ 14 ноября 2018

У меня огромное приложение с множеством вложенных действий, которое содержит фрагменты с большим количеством информации.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...