У меня возникла проблема при попытке динамического заполнения 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 не показывает, когда есть данные?
Нет, я нигде не устанавливал значение false, потому что он должен работать только один раз. Например, теперь, когда я нажал кнопку экспорта, мне удалось получить данные, но tableRow не отображается. Затем я щелкнул кнопку экспорта во второй раз, после этого отобразится tableRow, но проблема в том, что он даже не вошел в compileContent (). Поэтому мне интересно, почему tableRow не отображается в первый раз?
Кстати, а почему вы используете while?
@RickyMo, я думал, что использование цикла while сохранит его до тех пор, пока все 3 части не будут завершены? Я изменил его на оператор if, проблема все еще сохраняется
Прежде всего, !headerFinished && !footerFinished && !contentFinished означает, что если один из трех завершен, тело не будет выполнено, даже если два других не будут завершены. Вы, вероятно, захотите || вместо &&. Однако, если все три функции компиляции не содержат вызовов asycn, все они всегда должны завершаться после первой итерации, поэтому нет смысла использовать цикл.
Содержат ли ваши функции компиляции какие-либо асинхронные вызовы? Может быть, при первом создании PDF-файла данные не готовы? Попробуйте распечатать источник данных прямо перед его передачей в PDF-файл, чтобы увидеть, что вы получите.
@RickyMo Нет, не работает. Я изменил && на || и цикл while для оператора if, но tableRow все еще не заполняется при первом щелчке :(
@RickyMo Нет, compileHeader и compileFooter просто устанавливают текст в textview. Что касается содержимого, я использовал цикл for, опубликованный выше, для динамического добавления строки.
Согласно коду в buttonExportClicked() вы (пытаетесь) проверить, завершены ли определенные операции (предположительно), прежде чем создавать файл PDF. Но поскольку код «для создания pdf» находится вне цикла while, очевидно, PDF создается каждый раз, когда нажимается кнопка .. -> Я настоятельно рекомендую вам создать блок-схему и перестроить вашу логику. Посмотрите, как работают операторы if и что происходит, когда вы используете && или || логические операторы.
@Barns Yeap, это то, чего я пытаюсь достичь! У вас есть идеи, что мне нужно изменить, чтобы это работало?
Вы знаете свою программу намного лучше, чем я, поэтому я предлагаю вам составить блок-схему того, как эта часть вашей программы должна работать. Затем соответствующим образом сконструируйте логическую функциональность. Иногда блок-схема действительно может быть очень полезной. Удачи!
@RickyMo У вас есть идеи?
Как вы создаете свой PDF-файл?
Это настраиваемый класс, который не был создан мной :( Я думал, может быть проблема с логикой при нажатии кнопки экспорта?
лучше опубликуйте часть // code to generate pdf, чтобы показать, какие данные вы передаете этому классу.
@RickyMo Это строка: PdfGenerator.generatePdf (headerLayout, contentLayout, footerLayout, fileOutputStream); headerLayout, contentLayout будет заполнен в compileHeader (), compileContent (). Я все еще не мог понять, почему для отображения tableRow должно быть два клика
Вы пытались проверить, как выглядит contentLayout прямо в этой строке, когда он не работает?
@RickyMo У меня есть другое текстовое представление в compileContent, и они показывают правильный текст. Просто tableRow не заполняется при первом щелчке :( Итак, я думаю, что проблема в двух фрагментах кода, которые я опубликовал выше




Если я правильно понимаю, вы обновляете макеты и конвертируете макеты в 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) для ссылки на нулевой объект
Есть ли способ сделать так, чтобы 3 функции компиляции выполнялись сначала перед созданием pdf?
Как инициализировать summaryTableLayout? Если это null, то summaryTableLayout.addView(row); должен был сгенерировать исключение раньше ... Можно ли как-то изменить его потом?
Вы можете попробовать заменить summaryTableLayout.post на new Handler().post, посмотрите, поможет ли это
Я инициализировал его в compileContent ()!
да. Обновления пользовательского интерфейса автоматически отправляются в петлитель потока пользовательского интерфейса и не блокируют ваше текущее выполнение. Публикуя свою последующую операцию в цикле потока пользовательского интерфейса, вы можете гарантировать, что ваша последующая операция будет выполнена после завершения обновлений пользовательского интерфейса.
Почему вы используете
while? Вы имеете в видуif? Вы сбрасывалиcontentFinishedнаfalseгде-нибудь? В противном случаеcompileContent()не запустится во второй раз, поскольку состояниеwhileне выполнено.