Сбой Android runOnUiThread при нажатии кнопки «Назад»

Я использую DownloadManager для загрузки файлов с сервера, я делаю это с адаптера, и я показываю ход загрузки во фрагменте с помощью runOnUiThread. он отлично работает, но когда я нажимаю кнопку «Назад» во время загрузки, runOnUiThread выдает исключение NullPointerException. Я попытался поместить переменную в onPause с оператором if, чтобы остановить метод, но он тоже не работает.

что вы рекомендуете сделать, чтобы решить этот сбой?

вот мой код:

new Thread(new Runnable() {
                        @Override
                        public void run() {

                            downloading = true;

                            while (downloading) {

                                DownloadManager.Query q = new DownloadManager.Query();
                                q.setFilterById(myDownloadReference);

                                Cursor cursor = downloadManager.query(q);
                                cursor.moveToFirst();
                                int bytes_downloaded = cursor.getInt(cursor
                                        .getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
                                int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));

                                if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
                                    downloading = false;
                                    downloadingDocs.remove(doc);

                                    //remove the progressBar when download is complete
                                    fragment.getActivity().runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            finalHolder2.downloadProgress.setVisibility(View.INVISIBLE);
                                        }
                                    });

                                    //check if it's the last download and open it.
                                    if (downloadingDocs.size() == 0) {
                                        actionIntentOpenDocs(doc, saveFile);
                                    }
                                }
                                //final double dl_progress = (bytes_downloaded / bytes_total) * 100;
                                final int dl_progress = (int) ((bytes_downloaded * 100l) / bytes_total);

                                //display the download progress
                                fragment.getActivity().runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        if(Constants.stopUiThreadWork == null) {
                                            finalHolder2.downloadProgress.setProgress((int) dl_progress);
                                        }
                                    }
                                });
                                cursor.close();
                            }
                        }
                    }).start();

он падает в этой строке:

fragment.getActivity().runOnUiThread(new Runnable() {

Трассировка стека сбоя:

FATAL EXCEPTION: Thread-4807
Process: com.appus.app, PID: 6553
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.app.FragmentActivity.runOnUiThread(java.lang.Runnable)' on a null object reference
        at com.availo.app.UI.adapters.MainFragmentDocumentAdapter$1$1.run(MainFragmentDocumentAdapter.java:265)
        at java.lang.Thread.run(Thread.java:818)

person JozeRi    schedule 09.02.2015    source источник
comment
getActivity() возвращает null, если фрагмент не привязан ни к какому действию. Это происходит, если вы нажмете кнопку «Назад». Для вашего подхода рассмотрите возможность использования IntentService и уведомления для отображения хода выполнения.   -  person Christopher    schedule 09.02.2015
comment
Пожалуйста, опубликуйте трассировку стека сбоя, найденную в logcat.   -  person Anm    schedule 09.02.2015
comment
добавлена ​​трассировка стека Anm   -  person JozeRi    schedule 09.02.2015


Ответы (2)


Лучший способ управлять такими вещами – использовать Service. Причина в том, что служба может лучше управлять фоновыми потоками, даже если действие не выполняется, в то время как такие вещи, как AsyncTask, перестанут работать, когда действие будет выполнено. Взгляните на этот сайт, чтобы узнать, как настроить загрузку. Услуга.

person PearsonArtPhoto    schedule 09.02.2015

попробуйте проверить свою активность перед выполнением runOnUiThread следующим образом:

    /** check if activity still exist */
    if (getActivity() == null) {
        return;
    }

    getActivity().runOnUiThread(new Runnable() {
    ...
    });

"Вы не должны были засорять свой код возвратами? (...)"
"Чище" - вот где это становится двусмысленным. Мы не пишем на ассемблере, поэтому я не вижу, как это здесь уместно. Яблоки и апельсины. При написании методов наличие единственного возврата, где это возможно, улучшает читабельность и обслуживание. Если ваш код становится сложным или требует нескольких операторов возврата, следуя этому стилю кодирования, вероятно, метод требует дальнейшего анализа и разбивки. – Джулио

@giulio - ссылки, публикации, спецификации - я ничего не вижу в вашем комментарии - но я могу дать вам кое-что, чтобы прочитать и получить некоторые знания.

Вы можете начать отсюда, чтобы взорвать свой мозг:

а затем прочтите мою любимую:

http://www.yegor256.com/2015/08/18/multiple-return-statements-in-oop.html

person ceph3us    schedule 25.06.2015
comment
Правильная идея, но у вас не должно быть возврата в вашем коде. Вы можете выполнить то же самое более линейным способом, поместив runonUiThread в оператор if, тогда оператор return может не потребоваться. - person angryITguy; 26.08.2016
comment
вы не должны были засорять свой код возвратами? Зачем? вы когда-нибудь писали на ассемблере? - вы решаете поток кода :), если я хочу немедленно вернуться из метода, то я делаю это ... это чище, если/иначе также таким образом я подчеркиваю необходимость переменной в остальной части кода - я могу избежать другого :) и вложенные блоки - person ceph3us; 26.08.2016
comment
чище, где это становится двусмысленным. Мы не пишем на ассемблере, поэтому я не вижу, как это здесь уместно. Яблоки и апельсины. При написании методов наличие единственного возврата, где это возможно, улучшает читабельность и обслуживание. Если ваш код становится сложным или требует нескольких операторов возврата, следуя этому стилю кодирования, вероятно, метод требует дальнейшего анализа и разбивки. - person angryITguy; 27.08.2016
comment
@giulio - см. ответ - person ceph3us; 27.08.2016
comment
Я понимаю это в последнем абзаце. Использование альтернативных возвратов имело все проблемы оператора GOTO, с дополнительным усложнением, заключающимся в том, что условие перехода было не рядом с переходом, а где-то в подпрограмме. #рект - person angryITguy; 27.08.2016