我的自定义ListView太迟钝了

时间:2013-05-22 08:33:19

标签: android performance android-listview

我正在制作文件管理器。它的UI类似于Root Explorer的用户界面 但我将Root Access添加到我的文件管理器中,然后我的自定义列表视图非常滞后 我搜索了很多,但我还是无法解决它。

FileAdapter类代码:

public class FileAdapter extends BaseAdapter {
    private ArrayList<RootFileProperty> object;
    ImageLoader loader = new ImageLoader(getApplicationContext());
    boolean isScrolling = false;

    public FileAdapter(ArrayList<RootFileProperty> object) {
        super();
        this.object = object;
    }

    @Override
    public int getCount() {
        return object.size();
    }

    @Override
    public Object getItem(int arg0) {
        return null;
    }

    @Override
    public long getItemId(int arg0) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if(convertView == null) {
            LayoutInflater inflater = LayoutInflater.from(RootActivity.this);
            convertView = inflater.inflate(R.layout.rootrow, parent, false);
            holder = new ViewHolder();

            // Find View
            holder.fileicon = (ImageView) convertView.findViewById(R.id.icon);
            holder.filename = (TextView) convertView.findViewById(R.id.filename);
            holder.filedate = (TextView) convertView.findViewById(R.id.filedate);
            holder.fileperm = (TextView) convertView.findViewById(R.id.fileperm);
            holder.filesize = (TextView) convertView.findViewById(R.id.filesize);
            holder.check = (ImageView) convertView.findViewById(R.id.check);
            convertView.setTag(holder);
        }
        else holder = (ViewHolder) convertView.getTag();

        String filename = object.get(position).getName();
        String filedate = object.get(position).getDate();
        String fileperm = object.get(position).getPerm();
        String filesize = object.get(position).getSize();

        String txtPerm = fileperm.equals("") ? "" : fileperm + " [" + Integer.toString(calcPerm(fileperm)) + "]";

        String dir = nowPath.equals(root) ? nowPath + object.get(position).getName() : nowPath + "/" + object.get(position).getName();
        if(new RootFile(dir).isDirectory()) holder.fileicon.setImageDrawable(Folder);
        else
        {
            String file = getExtension(new RootFile(dir));
            String mimeType = getMIME(file);
            if (file.equals("zip") || 
                file.equals("7z")  || 
                file.equals("rar") ||
                file.equals("tar")) holder.fileicon.setImageDrawable(Compressed);

            else if(mimeType == null) holder.fileicon.setImageDrawable(Others);

            else if(mimeType.startsWith("image")) holder.fileicon.setImageDrawable(Image);

            else if(mimeType.startsWith("audio")) holder.fileicon.setImageDrawable(Audio);

            else if(file.equals("apk") && !isScrolling)
            {
                Bitmap b = ((BitmapDrawable) getApkIcon(dir)).getBitmap();
                loader.DisplayImage(object.get(position).getName(), b, holder.fileicon);
            }

            else if(file.equals("apk") && isScrolling)
            {
                holder.fileicon.setImageResource(R.drawable.android);
            }
        }

        holder.filename.setText(filename);
        holder.filedate.setText(filedate);
        holder.fileperm.setText(txtPerm);
        holder.filesize.setText(filesize);
        holder.check.setVisibility(isSelected[position]);
        return convertView;
    }
}

static class ViewHolder {
    ImageView fileicon;
    TextView filename;
    TextView filedate;
    TextView fileperm;
    TextView filesize;
    ImageView check;
}

我的rootrow.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rootrowlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >

<ImageView
    android:id="@+id/icon"
    android:layout_width="40dp"
    android:layout_height="40dp"
    android:src="@drawable/folder" />

<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="8"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/filename"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="10sp"
        android:textColor="?android:attr/textColorPrimary"
        android:textSize="17sp" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/filedate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingLeft="10sp"
            android:layout_marginRight="7dp"
            android:textColor="?android:attr/textColorSecondary"
            android:textSize="12sp" />

        <TextView
            android:id="@+id/fileperm"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="7dp"
            android:textSize="12sp" />

        <TextView
            android:id="@+id/filesize"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="?android:attr/textColorSecondary"
            android:textSize="12sp" />
    </LinearLayout>
</LinearLayout>

<ImageView
    android:id="@+id/check"
    android:layout_width="25sp"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:src="@drawable/check"
    android:visibility="invisible" />

</LinearLayout>

我的listview的一些设置

list = (ListView) findViewById(android.R.id.list);

    list.setOnItemLongClickListener(new OnItemLongClickListener() {
        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view,
                int position, long id) {
            SelectionItems(parent, position);
            if(showMultiSelectToast) { showToast(getString(R.string.NowStartMultiSelectMode)); showMultiSelectToast = false; }
            return true;
        }
    });

    list.setOnScrollListener(new OnScrollListener() {     
        public void onScrollStateChanged(AbsListView view, int scrollState) {   
            if (scrollState != 0)
                ((FileAdapter) list.getAdapter()).isScrolling = true;
            else {
                ((FileAdapter) list.getAdapter()).isScrolling = false;
                ((FileAdapter) list.getAdapter()).notifyDataSetChanged();
            }
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem,
                int visibleItemCount, int totalItemCount) {
        }
    });

    list.setScrollingCacheEnabled(false);

定义资源

res = getResources();
Folder = res.getDrawable(R.drawable.folder);
Others = res.getDrawable(R.drawable.others);
Image = res.getDrawable(R.drawable.image);
Audio = res.getDrawable(R.drawable.audio);
Compressed = res.getDrawable(R.drawable.compressed);

我的ImageLoader类与thest1's LazyList Project类似。

1 个答案:

答案 0 :(得分:0)

正如您应该知道的那样,在时间关键过程中创建新对象实例的性能非常糟糕。因此我们必须避免:

String mystring = new String();

实际上,如此topic所示,字符串连接又称:

String txtPerm = fileperm.equals("") ? "" : fileperm + " [" + Integer.toString(calcPerm(fileperm)) + "]";

将由编译器转换为:

StringBuilder sb = new StringBuilder(100); //bad for performances
    return sb.append("fileperm ").append("[" ).append(...);

您应该为所有人创建一个自己的StringBuilder实例,并在每个字符串连接opperation上重复使用它:

//global field
StringBuilder sb = new StringBuilder(100);

//any function that use concatenation
public String anyFunction(){

    [...]

    sb.clear(); //this is the trick : you don't creat new instance but clear the previous one to reuse it.
    String result = sb.append(fileperm)
                      .append('[')
                      .append(...);

    [...]

}

那应该更好。