我的应用程序中有一个ListView,并且我已经覆盖了getView()方法,因此我可以根据行的文本更改行的ImageView src。
问题是,我注意到ListView滚动滞后,当我检查DDMS时,似乎每次滚动ListView时都会调用垃圾收集器,从而减慢滚动速度。
我还注意到在我的应用程序的不同部分调用垃圾收集器时,从BufferedReader读取行,这使得打开一个2,000行文件需要大约47秒,其中作为文件exporer我安装在我的手机会在大约2秒内打开同一个文件。
所以我的问题是,每200ms左右可能导致不断的垃圾收集,我该如何预防呢?这真的会减慢我的应用程序速度,我担心如果我不解决它会让一些用户关闭。
谢谢, 亚历克斯。
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);
}
}
代码打开文件
我前几天删除了代码,记录了打开文件花了多少秒,但是花了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,它现在又开启了第二个 - 万岁!
2ND UPDATE:
我知道滚动ListView时常量GC调用的原因是什么,它是ListView属性android:cacheColorHint =“@ android:color / transparent” - 但我不知道解决方法!
答案 0 :(得分:1)
通常,垃圾收集正在发生,因为您不必要地创建了太多对象。帮助你的代码会更容易,但无论如何我都会试一试。
对于您的列表,您可能会在每次调用getView
时重新创建您的视图。相反,您应该在适当时重复使用convertView
。有关如何构建getView
方法的建议,请参阅我的answer至其他SO问题。
你的文件阅读问题有点难以猜测,但是对于2,000行来说,47s似乎非常长。你是否也在该循环中创建对象?
<强>更新强>
显然,你的问题与你自己的View
对象无关,但这是你每次获得View
时所做的所有工作。你每次都做了很多工作:一个RegEx匹配,字符串拆分(和相关的字符串对象创建)等。你应该至少缓存这个结果,这样你就不必为每个工作重做工作了。项目每次回到视图中。
答案 1 :(得分:1)
一种优化方法是停止拆分整个字符串以获取文件类型。你可以使用像
这样的东西String fileType = "";
int lastDot = entryFullFileName.lastIndexOf(".");
if(lastDot!=-1) {
fileType = entryFullFileName.substring()
}
但这当然不应该花费47秒。
答案 2 :(得分:0)
答案 3 :(得分:0)
是的,android:cacheColorHint =“@ android:color / transparent”导致在某些操作系统版本上过度调用垃圾收集器(不确定最新版本是否已修复)。
好吧,试着不要用它。例如,我与我的设计师交谈,向他们解释了滞后原因的问题,他们同意不使用透明背景。