Estou com o seguinte problema:
Minha aplicação, por fazer muito, mas muitos acessos a um banco de dados, demora para caregar.
Então, a idéia foi colocar um progress bar. Só que o java, na hora de executar todos os métodos, simplesmente instancia um componente, e antes mesmo de terminar de construí-lo, o java já instancia o proximo.
Isto acarreta que a barra de progresso chega ao fim muito, mas muito antes de toda a tela do aplicativo, que é formada por difeentes componentes, fique pronta.
Gostaria de saber se existe alguma meneira fazer com que a progress bar chegue ao fim somente quando toda a aplicação estiver carregada.
Meu problema não é em relação ao tempo. Só queria que a progress bar mostrasse exatamente o progresso de carga do meu aplicativo.
Pergunta 1: vc está instanciando objetos de onde? O Java tá usando várias threads pra instanciar os objetos? Eles por acaso vêm do banco??
Pergunta 2: Vc conta o objeto como “pronto” no construtor? O melhor é ter um método só pra isso que atualiza sua contagem, e chamá-lo no final da carga. Sempre no fim.
De modo geral, vc tem que atualizar o Monitor quando o objeto terminou de construir… eu sei que é meio óbvio, mas olhando bem pro seu código vc vai achar um lugar melhor pra colocá-lo.
Vou tentar ser mais claro.
Tenho uma classe principal que é um JFrame. Nesta JFrame, são instanciado e inseridos, entre outras coisas, um objeto Canvas, JToolBar, JTable, 3 JPanels.
Para isto, criei um método para instanciar e inserir cada um no JFrame. Exemplo: addCanvas(), addToolbar(), etc.
Daí criei um método que chama todos estes acima em sequencia. Entre a chama de cada um, eu vou aumentando a barra de progresso.
O Problema: A barra de progresso sempre chega ao seu final muito antes de todas os objetos terminarem de ser instanciados.
Dados importantes adicionais: Todas as classes citadas acima, sem excessão, fazem acesso a banco de dados. O canvas é o mais pesado de todos. Leva algo em torno de 50 segundos para teminar de carregar, pois precisa ir no banco buscar informações sobre o que ele deve pintar.
O que eu notei foi que ele chama, por exemplo, o método addCanvas(), e, sem esperar que o objeto seja totalmente intanciado, ele já chama o proximo método.
Não, não, não use a AWT Dispatcher pra fazer sua carga no banco! Vc vai ficar totalmente sem eventos…
Deixa eu perguntar: vc faz todas essas chamadas (por exemplo, a addCanvas() e ao método que aumenta o progresso) dentro do construtor??
O lance é que se vc compila com otimização, o Java pode trocar instruções de posição quando tem I/O. Já que todas as suas classes fazem I/O, ele acaba executando as instruções “off-screen” pra gerar os eventos o quanto antes.
Veja se seu comando pra compilar manda ele otimizar o código, e se tirar a otimização “parece” resolver. É claro que vc vai querer otimizar o seu código, então…
O tutorial da Sun “How to Use Progress Bars” também usa uma SwingWorker, um Objeto que executa uma tarefa e, quando terminado, faz alguma coisa no Swing.
A melhor abordagem é provavelmente criar um método updateProgress() que marca o seu progresso e chamá-lo ao longo das tarefas, e não entre métodos. Uma coisa que você pode fazer é declarar voláteis suas variáveis de instância:
public volatile Canvas canvas;
Isso impede o Java de trocar de ordem as leituras e as escritas dessa variável, portanto necessariamente esse código vai executar na ordem:
... // começo do método
addCanvas();
while (canvas == null); // busy wait
updateProgress();
Quando vc me mandou a outra instrução, e vi que no meu caso ela não tinha funcionado, também tentei invokeAndWait. Tinha um exemplo lá no java.
Ele melhora um pouco o carreagmento, pois ele espera um pouco antes de chamar a proxima instrução. Só que ño meu caso ele não funcionou. Chega-se ao fim das instruções antes do termino da criação das classes.
Vou tentar olhar este método q vc me falou lá na API, talvez eu esteja errando em algum lugar.
Mesmo asssim, valeu…
Vou tentar usar este método q vc me mandou novamente.