0

I'm making a file manager. It's UI is similar to Root Explorer's UI.
But I added Root Access to my file manager, then my custom listview is very laggy.
I searched a lot, but I couldn't fix it yet.

Code for FileAdapter Class:

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;
}

And my 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>

And some settings for my 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);

Defining Resources

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);

And My ImageLoader Class is similar to thest1's LazyList Project.

minty99
  • 327
  • 1
  • 2
  • 9
  • I think you are doing too many checks in the getView() method. Try to keep the code as small as possible. This will be triggered for every row and for every scroll. – rahul May 22 '13 at 08:55
  • @rahul but I made this logic as simple as possible... Do you know how to optimze this logic more? – minty99 May 22 '13 at 10:05

1 Answers1

0

As you should know, its really bad for performances to create new object instances during time critical process. thus we have to avoid :

String mystring = new String();

And actually, as seen in this topic, string concatenation aka:

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

will be turned by the compiler to :

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

You should create your own StringBuilder instance once for all and reuse it on each string concatenation 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(...);

    [...]

}

It should be better then.

Community
  • 1
  • 1
Guian
  • 4,563
  • 4
  • 34
  • 54
  • check that you apply it on any string concatenation and apply the same on "new RootFile(dir)" => shouldn't need to be created on each call. – Guian May 22 '13 at 12:03