gente. eu quase chorei.
abri meu app no topico "Tips & Tricks" e o terminal EXPLODIU. tipo, 733 erros por frame. o app ficou inutilizavel, travando, tudo quebrado. achei q era bug no meu checklist (pq ja tinha dado problema antes), mas nao era.
A Investigação (spoiler: foi o LaTeX)
passei um tempao arrumando o checklist (NoteChecklistContent). achei bugs reais la:
IntrinsicWidthbrigando comFlexible(conflito de constraints)Checkboxcom sizing zuado dentro deRowmainAxisSize: MainAxisSize.minnumRowcom filhosFlexible
corrigi tudo: troquei Checkbox por Icon + GestureDetector, Flexible → Expanded, etc. eram correções validas, mas nao resolveram o problema principal. (一_一)
ai redirecionei a saida do flutter run pra um arquivo de log e finalmente vi a cascata real:
| Erro | Quantidade |
|---|---|
| Invalid argument(s): string is not well-formed UTF-16 | 3 |
| RenderLine does not implement "computeDryBaseline" | 1 |
| RenderBox was not laid out: RenderIntrinsicWidth | 1 |
| RenderBox was not laid out: RenderIndexedSemantics | 288 |
| 'parentDataDirty' assertion failures | 440 |
| TOTAL | ~733/frame |
A Causa Raiz
o topico tinha uma nota com LaTeX inline: $E = mc^2$. o GptMarkdown converte $...$ pra \(...\) e manda pro flutter_math_fork renderizar via Math.tex().
acontece q o flutter_math_fork v0.7.4 usa uma classe RenderLine (custom RenderBox) que nao implementa computeDryBaseline, um metodo que virou obrigatorio no Flutter 3.38.
resultado: o RenderLine falha → o RenderIntrinsicWidth pai nao consegue fazer layout → o RenderIndexedSemantics (acessibilidade) falha em cascata → o framework detecta parentDataDirty em centenas de render objects → repete a cada frame. loop infinito de dor e sofrimento.
e o pior: nao tem versao nova de nenhum dos dois pacotes (gpt_markdown 1.1.5 e flutter_math_fork 0.7.4). os dois tao abandonados e incompativeis com Flutter 3.38. (ꐦ°᷄д°᷅)
O Workaround (sim, gambiarra)
ja q nao da pra usar o Math.tex() sem crashar, criei um builder seguro q renderiza LaTeX como texto estilizado (monospace + italico) em vez de formula bonitinha:
static Widget safeLatexBuilder(
BuildContext context,
String tex,
TextStyle textStyle,
bool inline,
) {
final theme = Theme.of(context);
return Text(
tex,
style: textStyle.copyWith(
fontFamily: 'monospace',
fontStyle: FontStyle.italic,
color: theme.colorScheme.onSurface.withValues(alpha: 0.85),
),
);
}
tambem fiz um pre-processamento proprio pra converter $...$ → \(...\) fora do GptMarkdown, pq o regex interno dele tava gerando strings UTF-16 malformadas:
static String _convertDollarLatex(String text) {
var result = text.replaceAllMapped(
RegExp(r'(?<!\\)\$\$(.*?)(?<!\\)\$\$', dotAll: true),
(match) => '\\[${match[1] ?? ""}\\]',
);
if (!result.contains(r'\(')) {
result = result.replaceAllMapped(
RegExp(r'(?<!\\)\$(.*?)(?<!\\)\$'),
(match) => '\\(${match[1] ?? ""}\\)',
);
}
return result;
}
ai chamei o GptMarkdown com useDollarSignsForLatex: false (ja q a conversao foi feita na mao) e apliquei o latexBuilder seguro em todos os lugares q usam GptMarkdown diretamente:
study_session_screen.dart(3 usos)edit_note_dialog.dart(1 uso)flashcard_bubble_content.dart(1 uso)
Resultado
| Metrica | Antes | Depois |
|---|---|---|
| parentDataDirty assertions | 440/frame | 0 |
| RenderBox was not laid out | 289/frame | 0 |
| computeDryBaseline errors | 1/frame | 0 |
| App usavel | nao | sim |
o trade-off eh q o LaTeX nao renderiza como formula bonita (aparece E = mc^2 em monospace em vez da formula formatada). mas pelo menos o app funciona. quando os mantenedores dos pacotes acordarem e lançarem update, eu reverto tudo.
sempre redirecione o log pra um arquivo. se eu tivesse ficado olhando o terminal scrollando 733 erros por frame eu nunca ia achar a causa raiz. e desconfie dos seus proprios palpites, eu perdi tempo no checklist sendo q o problema era o LaTeX o tempo todo. ¯\_(ツ)_/¯