I have a ListView in my app, and I've over-ridden the getView() method so I can change the row's ImageView src depending on the row's text.
The problem is, I've noticed the ListView scrolling is lagging, and when I check DDMS, it seems the Garbage Collector is being called everytime the ListView is being scrolled, thus slowing the scrolling.
I've also noticed the Garbage Collector being called in a different part of my app, when reading lines from a BufferedReader, which makes opening a 2,000 line file take ~47 seconds, where as a file exporer I have installed on my phone opens that same file in about 2 seconds.
So my question is, what could be causing the constant Garbage Collection every 200ms or so, and how do I prevent it? It's really slowing my app down and I fear it will put some users off if I don't solve it.
Thanks, Alex.
ListView getView():
class IconicAdapter extends ArrayAdapter<String> {
IconicAdapter(){
super(FileBrowser.this, R.layout.filebrowser_listview_row, R.id.listtext, directoryEntries);
}
@Override
public View getView(int position, View convertView, ViewGroup parent){
View row = super.getView(position, convertView, parent);
TextView text = (TextView) row.findViewById(R.id.listtext);
ImageView icon = (ImageView) row.findViewById(R.id.listicon);
entryFullFileName = directoryEntries.get(position).toString();
if(entryFullFileName.contains(".") && !entryFullFileName.matches("^\\.+$")){
String[] parts = entryFullFileName.split("\\.");
lastIndex = parts.length - 1;
fileType = parts[lastIndex];
}else{
fileType = "";
}
if(fileIsDir.get(position) == true){
icon.setImageResource(R.drawable.folderlightblue);
}else if(fileType.equals("html")){
icon.setImageResource(R.drawable.filehtml);
}else if(fileType.equals("css")){
icon.setImageResource(R.drawable.filecss);
}else if(fileType.equals("js")){
icon.setImageResource(R.drawable.filejs);
}else if(fileIsDir.get(position) == false){
icon.setImageResource(R.drawable.fileplain);
}
return(row);
}
}
Code To Open File
I removed the code the other day that logged how many seconds it took to open the file, but it took 47 seconds and definitely took too long, and again while the while loop is doing it's thing, there's constant calls to the Garbage Collector, which I'm guessing in the cause of the slow file reading - and yes, this function is called in a thread with progressDialog showing while the file is being read
private String getLocalFileContents(String fileUri){
try{
String contents = "";
BufferedReader in = new BufferedReader(new FileReader(fileUri));
String line;
while((line = in.readLine()) != null){
contents += line + "\n";
}
in.close();
return contents;
}catch(Exception e){
toast.setText("Failed to open sdcard file, try again.");
}
return null;
}
UPDATE:
The file reading problem is solved, turns out the String concatenation made the Garbage Collector get called after each loop, dramatically slowing the file reading down. As suggested by an answer I used StringBuilder instead and it now opens in a second - hooray!
2ND UPDATE:
I know what the cause of the constant GC calls when scrolling my ListView is, it's the ListView attribute android:cacheColorHint="@android:color/transparent" - but I don't know a work-around!