Salve a tutti,
faccio appello alle menti geniali Java di cui questo forum brulica per venire a capo di un problema.
Avete presente l'applet di Facebook per caricare le foto? Ecco, l'ho rifatto a casa e funziona a momenti pure meglio di quello, solo che c'è un problemino quando si tratta di mostrare le foto della directory, ed è il seguente:
Exception in thread "Image Fetcher 2" java.lang.OutOfMemoryError: Java heap space
Quando va a cercare nella directory, preleva tutte le jpg e le miniaturizza nel pannello centrale.
A parte che già questo processo è lento e se fosse possibile velocizzarlo... ma vediamo dopo, comunque mentre carica le miniature, ogni tanto salta fuori l'errore di cui sopra (con il numero di fetcher che cambia come vuole: fetcher 0, oppure fetcher 1, oppure fetcher 2...). Le immagini alla fine le carica lo stesso, però non è bello che lo dica... che si può fare?
Non so la riga precisa che dà l'errore, però posto il tratto di codice che carica le immagini, magari mi sapete suggerire la soluzione al problema, magari pure un modo più pratico,veloce ed ottimizzato per farlo e perché no pure qualche segreto per conquistare il mondo:
Questo è il metodo che cerca le immagini nella directory e ne lancia il caricamento (è un thread)
codice:
// load thread
public void run()
{
// caricamento: poiche' effettuare l'arrangiamento ad ogni immagine diventa un processo
// lungo e pesante, viene dunque adottato il seguente metodo: vengono prima caricate
// tutte le entry, disposte e visualizzate con arrange, ma senza caricare le immagini,
// le stesse verranno caricate man mano in secondo momento. Questo metodo evita il richiamo
// di arrange ad ogni aggiunta. Certo richiede due cicli invece di uno, ma n chiamate in
// meno ad arrange sono comunque un guadagno considerevole che nasconde totalmente la
// perdita del doppio ciclo.
if(vRun) //se attivo
{
try{
vImageList.clear();
File dir=new File(vDirectory);
File[] imgpaths=dir.listFiles(new JPG_Filter());
if(imgpaths!=null)
{
// rilevamento e inizializzazione delle entry
for(int i=0;i<imgpaths.length;i++)
{
if(!vRun)
break; //interruzione
ImageEntry e=new ImageEntry(null,vMaxW,vMaxH);
if(vSelectionList.contains(imgpaths[i].getAbsolutePath()))
e.select();
else
e.unselect();
if(vSentList.contains(imgpaths[i].getAbsolutePath()))
e.sent();
else
e.notSent();
vImageList.add(e);
}
arrange();
repaint();
// caricamento delle immagini
for(int i=0;i<imgpaths.length;i++)
{
if(!vRun)
break; //interruzione
vImageList.elementAt(i).setPathname(imgpaths[i].getAbsolutePath());
vImageList.elementAt(i).beginLoad(this); //innesca il caricamento
//repaint();
}
}
}catch(Exception e){
System.out.println("Errore del thread: "+e.getMessage());
}
// non aggiunge (add) per non sconvolgere il layout
repaint();
vRun=false; //arresta l'esecuzione
}
}
Questa è la procedura setPathname() di ImageEntry, che sarebbero gli elementi di vImageList, la quale carica l'oggetto con la miniatura
codice:
public void setPathname(String path) throws Exception
{
vInfo=new File(path);
vText=vInfo.getName();
Image img=Toolkit.getDefaultToolkit().getImage(path);
MediaTracker mt=new MediaTracker(this);
mt.addImage(img,0);
mt.waitForID(0);
// calcolo del lato vincolato
int W=img.getWidth(this),H=img.getHeight(this);
if(W>vMaxW || H>vMaxH) //il tutto viene svolto se qualche dimensione sfora
{
int newW,newH;
newH=(H*vMaxW)/W; //altezza se fisso l'altezza
newW=(W*vMaxH)/H; //larghezza se fisso l'altezza
if(newH>vMaxH) //se l'altezza e' piu' del limite dall'algoritmo
{
// ridimensiono in base all'altezza
// fisso l'altezza e la larghezza si regola di conseguenza
newH=vMaxH;
}
else
{
// altrimenti ridimensiono in base alla larghezza
// fisso la larghezza e l'altezza si regola di conseguenza
newW=vMaxW;
}
// a questo punto ho le nuove dimensioni adattate nei limiti in newW e newH
vThumbnail=img.getScaledInstance(newW,newH,Image.SCALE_FAST);
}
else
vThumbnail=img;
}
Questa è la beginLoad() che viene chiamata una volta nelle immagini serve solo a lanciare il caricamento delle miniature...ma lo scrivo lo stesso
codice:
public void beginLoad(ImageObserver obj)
{
if(vThumbnail!=null) // vThumbnail è un Image della miniatura
{
vThumbnail.getWidth(obj);
}
}
Una cosa: il codice sembra libero da memory leak, parola di profiler, il quale mi dice pure che, per una cartella che dà il problema, la memoria usata si innalza a 60 MB e rimane lì fino alla fine della procedura (che intanto exceptiona allegramente).
Se ho dimenticato qualcosa o se avete una qualche idea e/o suggerimento, sono qui...
HSH
ciauz