Заполнение TableRow динамически не работает

У меня возникла проблема при попытке динамического заполнения TableRow. Я пытаюсь сделать, нажимая кнопку экспорта, я компилирую заголовок, нижний колонтитул и контент, а затем, когда они будут выполнены, я перехожу к экспорту в формате PDF.

Я заполнил свой TableLayout следующим кодом в compileContent ():

for (int i = 0; i < allCalibrationList.size(); i++) {
        System.out.println("DATA" + allCalibrationList.get(i).getCalibrationName());
        TableRow row = (TableRow) getLayoutInflater().inflate(R.layout.template_calibration_report_summary_item, summaryTableLayout, false);
        TextView textCol1 = row.findViewById(R.id.row_col1);
        TextView textCol2 = row.findViewById(R.id.row_col2);

        textCol1.setText(allCalibrationList.get(i).getCalibrationName());
        textCol2.setText(getString(R.string.report_not_calibrated_label));
        
        summaryTableLayout.addView(row);
    }
    contentFinished = true;

Когда моя кнопка экспорта при нажатии:

@Click(R.id.buttonExport)
void buttonExportClicked(View view) {
    FileOutputStream fileOutputStream;
    try {
        while (!headerFinished && !footerFinished && !contentFinished) {
            compileHeader();
            compileContent();
            compileFooter();
        }
        // code to generate pdf
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Проблема в том, что когда я впервые нажимаю кнопку экспорта, она попадает в compileContent(), и из напечатанного сообщения, которое я вставил в цикл for, мне удалось распечатать данные. Однако tableRow не отображается в экспортированном PDF-файле. tableRow будет отображаться только при втором нажатии кнопки экспорта.

Однако, когда я нажимаю кнопку экспорта во второй раз, она не попадает в compileContent(), поскольку напечатанное сообщение, которое я установил для цикла, не печатается. Почему это так? Почему tableRow не показывает, когда есть данные?

Почему вы используете while? Вы имеете в виду if? Вы сбрасывали contentFinished на false где-нибудь? В противном случае compileContent() не запустится во второй раз, поскольку состояние while не выполнено.

Ricky Mo 03.10.2018 03:43

Нет, я нигде не устанавливал значение false, потому что он должен работать только один раз. Например, теперь, когда я нажал кнопку экспорта, мне удалось получить данные, но tableRow не отображается. Затем я щелкнул кнопку экспорта во второй раз, после этого отобразится tableRow, но проблема в том, что он даже не вошел в compileContent (). Поэтому мне интересно, почему tableRow не отображается в первый раз?

dummygg 03.10.2018 03:45

Кстати, а почему вы используете while?

zihadrizkyef 03.10.2018 03:45

@RickyMo, я думал, что использование цикла while сохранит его до тех пор, пока все 3 части не будут завершены? Я изменил его на оператор if, проблема все еще сохраняется

dummygg 03.10.2018 03:46

Прежде всего, !headerFinished && !footerFinished && !contentFinished означает, что если один из трех завершен, тело не будет выполнено, даже если два других не будут завершены. Вы, вероятно, захотите || вместо &&. Однако, если все три функции компиляции не содержат вызовов asycn, все они всегда должны завершаться после первой итерации, поэтому нет смысла использовать цикл.

Ricky Mo 03.10.2018 03:53

Содержат ли ваши функции компиляции какие-либо асинхронные вызовы? Может быть, при первом создании PDF-файла данные не готовы? Попробуйте распечатать источник данных прямо перед его передачей в PDF-файл, чтобы увидеть, что вы получите.

Ricky Mo 03.10.2018 03:56

@RickyMo Нет, не работает. Я изменил && на || и цикл while для оператора if, но tableRow все еще не заполняется при первом щелчке :(

dummygg 03.10.2018 03:57

@RickyMo Нет, compileHeader и compileFooter просто устанавливают текст в textview. Что касается содержимого, я использовал цикл for, опубликованный выше, для динамического добавления строки.

dummygg 03.10.2018 03:58

Согласно коду в buttonExportClicked() вы (пытаетесь) проверить, завершены ли определенные операции (предположительно), прежде чем создавать файл PDF. Но поскольку код «для создания pdf» находится вне цикла while, очевидно, PDF создается каждый раз, когда нажимается кнопка .. -> Я настоятельно рекомендую вам создать блок-схему и перестроить вашу логику. Посмотрите, как работают операторы if и что происходит, когда вы используете && или || логические операторы.

Barns 03.10.2018 04:05

@Barns Yeap, это то, чего я пытаюсь достичь! У вас есть идеи, что мне нужно изменить, чтобы это работало?

dummygg 03.10.2018 04:10

Вы знаете свою программу намного лучше, чем я, поэтому я предлагаю вам составить блок-схему того, как эта часть вашей программы должна работать. Затем соответствующим образом сконструируйте логическую функциональность. Иногда блок-схема действительно может быть очень полезной. Удачи!

Barns 03.10.2018 04:16

@RickyMo У вас есть идеи?

dummygg 03.10.2018 05:01

Как вы создаете свой PDF-файл?

Ricky Mo 03.10.2018 05:03

Это настраиваемый класс, который не был создан мной :( Я думал, может быть проблема с логикой при нажатии кнопки экспорта?

dummygg 03.10.2018 05:05

лучше опубликуйте часть // code to generate pdf, чтобы показать, какие данные вы передаете этому классу.

Ricky Mo 03.10.2018 05:09

@RickyMo Это строка: PdfGenerator.generatePdf (headerLayout, contentLayout, footerLayout, fileOutputStream); headerLayout, contentLayout будет заполнен в compileHeader (), compileContent (). Я все еще не мог понять, почему для отображения tableRow должно быть два клика

dummygg 03.10.2018 05:26

Вы пытались проверить, как выглядит contentLayout прямо в этой строке, когда он не работает?

Ricky Mo 03.10.2018 05:29

@RickyMo У меня есть другое текстовое представление в compileContent, и они показывают правильный текст. Просто tableRow не заполняется при первом щелчке :( Итак, я думаю, что проблема в двух фрагментах кода, которые я опубликовал выше

dummygg 03.10.2018 05:32
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
18
43
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если я правильно понимаю, вы обновляете макеты и конвертируете макеты в PDF с помощью специального класса. Обновление макетов означает обновление пользовательского интерфейса, которое обычно не завершается сразу, поскольку обновления пользовательского интерфейса ставятся в очередь и будут выполняться позже в потоке пользовательского интерфейса. (Вот почему, когда ваше устройство занято и тормозит, пользовательский интерфейс обновляется недостаточно быстро)

TableRow, который вы надуваете, может не закончиться при создании PDF из-за того, как работает надувной модуль Android. Вы можете использовать View.post () для запуска кода после завершения наполнения представления. Попробуй это:

@Click(R.id.buttonExport)
void buttonExportClicked(View view) {
    FileOutputStream fileOutputStream;
    try {
        if (!headerFinished || !footerFinished || !contentFinished) {
            compileHeader();
            compileContent();
            compileFooter();
        }
        summaryTableLayout.post(new Runnable(){
           @Override
           public void run() {
               // code to generate pdf
           }

        })

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Да, это то, что я пытаюсь сделать! Однако после добавления .post я получаю это сообщение об ошибке: Попытка вызвать виртуальный метод boolean android.widget.TableLayout.post (java.lang.Runnable) для ссылки на нулевой объект

dummygg 03.10.2018 07:47

Есть ли способ сделать так, чтобы 3 функции компиляции выполнялись сначала перед созданием pdf?

dummygg 03.10.2018 08:01

Как инициализировать summaryTableLayout? Если это null, то summaryTableLayout.addView(row); должен был сгенерировать исключение раньше ... Можно ли как-то изменить его потом?

Ricky Mo 03.10.2018 08:57

Вы можете попробовать заменить summaryTableLayout.post на new Handler().post, посмотрите, поможет ли это

Ricky Mo 03.10.2018 09:05

Я инициализировал его в compileContent ()!

dummygg 03.10.2018 09:09

да. Обновления пользовательского интерфейса автоматически отправляются в петлитель потока пользовательского интерфейса и не блокируют ваше текущее выполнение. Публикуя свою последующую операцию в цикле потока пользовательского интерфейса, вы можете гарантировать, что ваша последующая операция будет выполнена после завершения обновлений пользовательского интерфейса.

Ricky Mo 03.10.2018 09:22

Другие вопросы по теме