我的应用程序中有一个 ListView,并且我重写了 getView() 方法,因此我可以根据行的文本更改行的 ImageView src。
问题是,我注意到 ListView 滚动滞后,当我检查 DDMS 时,似乎每次滚动 ListView 时都会调用垃圾收集器,从而减慢滚动速度。
我还注意到垃圾收集器在我的应用程序的不同部分被调用,当从 BufferedReader 读取行时,这使得打开一个 2,000 行文件需要大约 47 秒,而我在手机上安装的文件导出器打开了在大约 2 秒内完成相同的文件。
所以我的问题是,什么可能导致每隔 200 毫秒左右进行一次持续的垃圾收集,我该如何防止呢?这真的让我的应用程序变慢了,我担心如果我不解决它会让一些用户失望。
谢谢,亚历克斯。
列表视图 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);
}
}
打开文件的代码
前几天我删除了记录打开文件需要多少秒的代码,但它花了 47 秒,而且肯定花了太长时间,而且当 while 循环正在做这件事时,不断调用垃圾收集器,它我猜是文件读取速度慢的原因 - 是的,这个函数是在一个线程中调用的,在读取文件时显示progressDialog
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;
}
更新:
文件读取问题解决了,结果字符串连接使垃圾收集器在每个循环后被调用,大大减慢了文件读取速度。正如答案所建议的那样,我改用 StringBuilder ,现在它会在一秒钟内打开 - 万岁!
第二次更新:
我知道滚动我的 ListView 时不断调用 GC 的原因是什么,它是 ListView 属性 android:cacheColorHint="@android:color/transparent" - 但我不知道解决方法!