OSDN Git Service

CMFM: improved search performance
authorRoman Birg <roman@cyngn.com>
Wed, 29 Jul 2015 00:24:15 +0000 (17:24 -0700)
committerRoman Birg <roman@cyngn.com>
Thu, 13 Aug 2015 16:44:47 +0000 (09:44 -0700)
Search was usable with a small number of results, but when the result
list grows to something > 1000, it can get really laggy.

A few improvemnts:
- The adapter was chunking items and adding them in bulk to the adapter,
  but it was doing all the work in the main thread. Now it will process
  one item at a time, doing all the rough work in an AsyncTask, and
  passing the final objects to the adapter.

- We don't need to do any chunking of items to add them, but sorting
  the list as soon as they are added is expensive too, so re-use the
  streaming mechanism that was used to add items in chunks, and just
  sort the list during that time.

- Cache common variables to not look them up on every result

- Use a List instead of generating a new DataHolder array _every time_ a
  new object was added. It would end up GCing thousands of items
  every time a new result was added.

- Make the adapter be as simple as possible and just display DataHolder
  objects so it doesn't have to do any processing.

Ref: QRDL-950

Change-Id: I17dd606246556cdf2701bbf2b06933f138588d74
Signed-off-by: Roman Birg <roman@cyngn.com>
src/com/cyanogenmod/filemanager/activities/NavigationActivity.java
src/com/cyanogenmod/filemanager/activities/SearchActivity.java
src/com/cyanogenmod/filemanager/adapters/SearchResultAdapter.java

index e4d6b10..716f917 100755 (executable)
@@ -478,6 +478,8 @@ public class NavigationActivity extends Activity
 
     private boolean mNeedsEasyMode = false;
 
+    private boolean mDisplayingSearchResults;
+
     /**
      * @hide
      */
@@ -630,10 +632,6 @@ public class NavigationActivity extends Activity
     protected void onStart() {
         super.onStart();
 
-        if (mSearchView.getVisibility() == View.VISIBLE) {
-            closeSearch();
-        }
-
         // Check restrictions
         if (!FileManagerApplication.checkRestrictSecondaryUsersAccess(this, mChRooted)) {
             return;
@@ -649,7 +647,13 @@ public class NavigationActivity extends Activity
                 onRequestBookmarksRefresh();
                 removeUnmountedHistory();
                 removeUnmountedSelection();
+            }
 
+            if (mDisplayingSearchResults) {
+                mDisplayingSearchResults = false;
+                closeSearch();
+            } else {
+                getCurrentNavigationView().refresh(true);
                 Intent intent = new Intent();
                 intent.putExtra(EXTRA_ADD_TO_HISTORY, false);
                 initNavigation(NavigationActivity.this.mCurrentNavigationView, false, intent);
@@ -1577,14 +1581,16 @@ public class NavigationActivity extends Activity
      * @hide
      */
     void initNavigation(final int viewId, final boolean restore, final Intent intent) {
+        if (mDisplayingSearchResults || restore) {
+            return;
+        }
+
         final NavigationView navigationView = getNavigationView(viewId);
         this.mHandler.post(new Runnable() {
             @Override
             public void run() {
                 //Is necessary navigate?
-                if (!restore) {
-                    applyInitialDir(navigationView, intent);
-                }
+                applyInitialDir(navigationView, intent);
             }
         });
     }
@@ -1935,6 +1941,7 @@ public class NavigationActivity extends Activity
                                 //Goto to new directory
                                 getCurrentNavigationView().open(fso, searchInfo);
                                 performHideEasyMode();
+                                mDisplayingSearchResults = true;
                             }
                         }
                     } else if (resultCode == RESULT_CANCELED) {
index b7626e8..86e6e4a 100755 (executable)
@@ -29,7 +29,9 @@ import android.content.IntentFilter;
 import android.content.res.Configuration;
 import android.graphics.Color;
 import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.preference.PreferenceActivity;
@@ -37,7 +39,6 @@ import android.provider.SearchRecentSuggestions;
 import android.text.Html;
 import android.text.TextUtils;
 import android.util.Log;
-import android.view.KeyEvent;
 import android.view.MenuItem;
 import android.view.View;
 import android.widget.AdapterView;
@@ -69,9 +70,11 @@ import com.cyanogenmod.filemanager.model.SearchResult;
 import com.cyanogenmod.filemanager.model.Symlink;
 import com.cyanogenmod.filemanager.parcelables.SearchInfoParcelable;
 import com.cyanogenmod.filemanager.preferences.AccessMode;
+import com.cyanogenmod.filemanager.preferences.DisplayRestrictions;
 import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
 import com.cyanogenmod.filemanager.preferences.Preferences;
 import com.cyanogenmod.filemanager.providers.RecentSearchesContentProvider;
+import com.cyanogenmod.filemanager.ui.IconHolder;
 import com.cyanogenmod.filemanager.ui.ThemeManager;
 import com.cyanogenmod.filemanager.ui.ThemeManager.Theme;
 import com.cyanogenmod.filemanager.ui.dialogs.ActionsDialog;
@@ -91,11 +94,15 @@ import com.cyanogenmod.filemanager.util.MimeTypeHelper.MimeTypeCategory;
 import com.cyanogenmod.filemanager.util.SearchHelper;
 import com.cyanogenmod.filemanager.util.StorageHelper;
 
+import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.Serializable;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 
 /**
  * An activity for search files and folders.
@@ -181,7 +188,7 @@ public class SearchActivity extends Activity
             try {
                 // Response if the item can be removed
                 SearchResultAdapter adapter = (SearchResultAdapter)parent.getAdapter();
-                SearchResult result = adapter.getItem(position);
+                SearchResult result = adapter.getItem(position).getSearchResult();
                 if (result != null && result.getFso() != null) {
                     if (result.getFso() instanceof ParentDirectory) {
                         // This is not possible ...
@@ -202,7 +209,7 @@ public class SearchActivity extends Activity
             try {
                 // Response if the item can be removed
                 SearchResultAdapter adapter = (SearchResultAdapter)parent.getAdapter();
-                SearchResult result = adapter.getItem(position);
+                SearchResult result = adapter.getItem(position).getSearchResult();
                 if (result != null && result.getFso() != null) {
                     DeleteActionPolicy.removeFileSystemObject(
                             SearchActivity.this,
@@ -377,6 +384,12 @@ public class SearchActivity extends Activity
     private SearchResultAdapter mAdapter;
     private ProgressBar mStreamingSearchProgress;
     private boolean mSearchInProgress;
+    private String mSearchFoundString;
+    private boolean mHighlightTerms;
+    private boolean mShowRelevanceWidget;
+    private int mHighlightColor;
+    private ArrayList<DataHolder> mAdapterList = new ArrayList<>();
+    private IconHolder mIconHolder;
 
     /**
      * {@inheritDoc}
@@ -390,6 +403,13 @@ public class SearchActivity extends Activity
         // Check if app is running in chrooted mode
         this.mChRooted = FileManagerApplication.getAccessMode().compareTo(AccessMode.SAFE) == 0;
 
+        final boolean displayThumbs = Preferences.getSharedPreferences().getBoolean(
+                FileManagerSettings.SETTINGS_DISPLAY_THUMBS.getId(),
+                ((Boolean)FileManagerSettings.SETTINGS_DISPLAY_THUMBS.getDefaultValue()).booleanValue());
+        mIconHolder = new IconHolder(this, displayThumbs);
+        mIconHolder.getDrawable("ic_fso_folder_drawable"); //$NON-NLS-1$
+        mIconHolder.getDrawable("ic_fso_default_drawable"); //$NON-NLS-1$
+
         // Register the broadcast receiver
         IntentFilter filter = new IntentFilter();
         filter.addAction(FileManagerSettings.INTENT_SETTING_CHANGED);
@@ -431,6 +451,10 @@ public class SearchActivity extends Activity
             }
         }
 
+        mSearchFoundString = getString(R.string.search_found_items_in_directory);
+        //$NON-NLS-1$
+        mHighlightColor = theme.getColor(this, "search_highlight_color");
+
         //Save state
         super.onCreate(state);
     }
@@ -720,6 +744,7 @@ public class SearchActivity extends Activity
                                 back(true, null, false);
                             }
                        });
+        dialog.setCancelable(false);
         DialogHelper.delegateDialogShow(this, dialog);
     }
 
@@ -733,6 +758,15 @@ public class SearchActivity extends Activity
      */
     void doSearch(
             final boolean voiceQuery, final Query query, final String searchDirectory) {
+        // Load settings
+        this.mHighlightTerms = Preferences.getSharedPreferences().getBoolean(
+                FileManagerSettings.SETTINGS_HIGHLIGHT_TERMS.getId(),
+                ((Boolean)FileManagerSettings.SETTINGS_HIGHLIGHT_TERMS.
+                        getDefaultValue()).booleanValue());
+        this.mShowRelevanceWidget = Preferences.getSharedPreferences().getBoolean(
+                FileManagerSettings.SETTINGS_SHOW_RELEVANCE_WIDGET.getId(),
+                ((Boolean)FileManagerSettings.SETTINGS_SHOW_RELEVANCE_WIDGET.
+                        getDefaultValue()).booleanValue());
 
         // Recovers the user preferences about save suggestions
         boolean saveSuggestions = Preferences.getSharedPreferences().getBoolean(
@@ -761,7 +795,8 @@ public class SearchActivity extends Activity
         this.mResultList = new ArrayList<FileSystemObject>();
         mAdapter =
                 new SearchResultAdapter(this,
-                        new ArrayList<SearchResult>(), R.layout.search_item, this.mQuery);
+                        mAdapterList, R.layout.search_item,
+                        this.mQuery, mIconHolder);
         this.mSearchListView.setAdapter(mAdapter);
 
         //Set terms
@@ -811,25 +846,84 @@ public class SearchActivity extends Activity
         });
     }
 
+    private static class ProcessSearchResult extends AsyncTask<FileSystemObject, Void, Boolean> {
+
+        private WeakReference<SearchActivity> mActivity;
+
+        private SearchResult mResult;
+        private DataHolder mHolder;
+
+        public ProcessSearchResult(SearchActivity parent) {
+            super();
+            mActivity = new WeakReference<SearchActivity>(parent);
+        }
+
+        @Override
+        protected Boolean doInBackground(FileSystemObject... params) {
+            SearchActivity activity = mActivity.get();
+            if (activity == null) {
+                return false;
+            }
+
+            FileSystemObject result = params[0];
+            // check against user's display preferences
+            if ( !FileHelper.compliesWithDisplayPreferences(result, null, activity.mChRooted) ) {
+                return false;
+            }
+
+            // resolve sym links
+            FileHelper.resolveSymlink(activity, result);
+
+            // convert to search result
+            mResult = SearchHelper.convertToResult(result, activity.mQuery);
+
+            mHolder = activity.generateDataHolder(mResult);
+
+            return mHolder != null && mResult != null;
+        }
+
+        @Override
+        protected void onPostExecute(Boolean sucess) {
+            SearchActivity activity = mActivity.get();
+            if (activity == null) {
+                return;
+            }
+            if (sucess) {
+                // add to adapter
+                activity.mAdapter.addNewItem(mHolder);
+            }
+        }
+    }
+
     /**
      * Ensures the search result meets user preferences and passes it to the adapter for display
      *
      * @param result FileSystemObject that matches the search result criteria
      */
     private void showSearchResult(FileSystemObject result) {
-        // check against user's display preferences
-        if ( !FileHelper.compliesWithDisplayPreferences(result, null, mChRooted) ) {
-            return;
-        }
-
-        // resolve sym links
-        FileHelper.resolveSymlink(this, result);
-
-        // convert to search result
-        SearchResult searchResult = SearchHelper.convertToResult(result, mQuery);
+        new ProcessSearchResult(this).execute(result);
+    }
 
-        // add to adapter
-        mAdapter.addNewItem(searchResult);
+    private DataHolder generateDataHolder(SearchResult result) {
+        //Build the data holder
+        final FileSystemObject fso = result.getFso();
+        final Drawable icon = mIconHolder.getDrawable(
+                MimeTypeHelper.getIcon(this, fso));
+        final CharSequence highlightedName;
+        if (mHighlightTerms) {
+            highlightedName = SearchHelper.getHighlightedName(result, mQuery.getQueries(),
+                    mHighlightColor);
+        } else {
+            highlightedName = SearchHelper.getNonHighlightedName(result);
+        }
+        final String parent = new File(result.getFso().getFullPath()).getParent();
+        Float relevance = mShowRelevanceWidget ? ((float)result.getRelevance() * 100)
+                / SearchResult.MAX_RELEVANCE : null;
+        final MimeTypeHelper.MimeTypeCategory category = MimeTypeHelper.getCategory(this, fso);
+
+        SearchActivity.DataHolder holder = new SearchActivity.DataHolder(result, icon,
+                highlightedName, parent, relevance, category);
+        return holder;
     }
 
     /**
@@ -841,6 +935,12 @@ public class SearchActivity extends Activity
             public void run() {
                 //Toggle results
                 List<SearchResult> list = SearchActivity.this.mRestoreState.getSearchResultList();
+                mAdapterList.clear();
+                for (SearchResult searchResult : list) {
+                    mAdapterList.add(generateDataHolder(searchResult));
+                }
+
+
                 String directory = SearchActivity.this.mRestoreState.getSearchDirectory();
                 SearchActivity.this.toggleResults(list.size() > 0, true);
                 setFoundItems(list.size(), directory);
@@ -869,9 +969,9 @@ public class SearchActivity extends Activity
                     SearchResultAdapter adapter =
                             new SearchResultAdapter(
                                                 SearchActivity.this.mSearchListView.getContext(),
-                                                list,
+                                                mAdapterList,
                                                 R.layout.search_item,
-                                                query);
+                                                query, mIconHolder);
                     SearchActivity.this.mSearchListView.setAdapter(adapter);
                     SearchActivity.this.mSearchListView.setSelection(0);
 
@@ -960,11 +1060,8 @@ public class SearchActivity extends Activity
                             getResources().
                                 getQuantityString(
                                     R.plurals.search_found_items, items, Integer.valueOf(items));
-                    SearchActivity.this.mSearchFoundItems.setText(
-                                            getString(
-                                                R.string.search_found_items_in_directory,
-                                                foundItems,
-                                                directory));
+                    SearchActivity.this.mSearchFoundItems.setText(String.format(mSearchFoundString,
+                            foundItems, directory));
                 }
             });
         }
@@ -1010,7 +1107,8 @@ public class SearchActivity extends Activity
         if (mSearchInProgress) mExecutable.end();
 
         try {
-            SearchResult result = ((SearchResultAdapter)parent.getAdapter()).getItem(position);
+            SearchResult result = ((SearchResultAdapter)parent.getAdapter()).getItem(position)
+                    .getSearchResult();
             FileSystemObject fso = result.getFso();
             if (fso instanceof Directory) {
                 back(false, fso, false);
@@ -1097,7 +1195,7 @@ public class SearchActivity extends Activity
 
         // Get the adapter, the search result and the fso
         SearchResultAdapter adapter = ((SearchResultAdapter)parent.getAdapter());
-        SearchResult searchResult = adapter.getItem(position);
+        SearchResult searchResult = adapter.getItem(position).getSearchResult();
         FileSystemObject fso = searchResult.getFso();
 
         // Open the actions menu
@@ -1147,8 +1245,7 @@ public class SearchActivity extends Activity
         if (adapter != null) {
             int pos = adapter.getPosition(fso);
             if (pos != -1) {
-                SearchResult sr = adapter.getItem(pos);
-                adapter.remove(sr);
+                adapter.remove(adapter.getItem(pos));
             }
 
             // Toggle resultset?
@@ -1171,7 +1268,7 @@ public class SearchActivity extends Activity
                 FileSystemObject fso = (FileSystemObject)o;
                 int pos = adapter.getPosition(fso);
                 if (pos >= 0) {
-                    SearchResult sr = adapter.getItem(pos);
+                    SearchResult sr = adapter.getItem(pos).getSearchResult();
                     sr.setFso(fso);
                 }
             } else if (o == null) {
@@ -1302,7 +1399,6 @@ public class SearchActivity extends Activity
      * Method that navigate to the file system used the intent (NavigationActivity)
      *
      * @param fso The file system object to navigate to
-     * @param intent The intent used to navigate to
      * @return boolean If the action implies finish this activity
      */
     boolean navigateTo(FileSystemObject fso) {
@@ -1379,10 +1475,46 @@ public class SearchActivity extends Activity
 
     @Override
     public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
-        String category = MimeTypeHelper.MimeTypeCategory.names()[i];
+        final String category = MimeTypeHelper.MimeTypeCategory.names()[i];
         SearchResultAdapter adapter = ((SearchResultAdapter) this.mSearchListView.getAdapter());
         if (adapter != null) {
-            adapter.setMimeFilter(category);
+            new AsyncTask<String, Void, Void>() {
+                List<DataHolder> mNewList = new ArrayList<>();
+                @Override
+                protected Void doInBackground(String... params) {
+                    // Are we in ChRooted environment?
+                    boolean chRooted =
+                            FileManagerApplication.getAccessMode().compareTo(AccessMode.SAFE) == 0;
+
+                    // Create display restrictions
+                    Map<DisplayRestrictions, Object> restrictions =
+                            new HashMap<DisplayRestrictions, Object>();
+                    restrictions.put(
+                            DisplayRestrictions.MIME_TYPE_RESTRICTION, MimeTypeHelper.ALL_MIME_TYPES);
+
+                    List<SearchResult> newResults = SearchHelper.convertToResults(
+                            FileHelper.applyUserPreferences(
+                                    mAdapter.getFiles(), restrictions, true, chRooted), new Query().fillSlots(mQuery.getQueries()));
+
+                    for (SearchResult result : newResults) {
+                        // Only show results that are within our category, or all if no filter is set
+                        if (TextUtils.equals(category, MimeTypeHelper.MimeTypeCategory.NONE.name()) ||
+                                MimeTypeHelper.getCategory(SearchActivity.this, result.getFso()) ==
+                                        MimeTypeHelper.MimeTypeCategory.valueOf(category)) {
+                            mNewList.add(generateDataHolder(result));
+                        }
+                    }
+                    return null;
+                }
+
+                @Override
+                protected void onPostExecute(Void aVoid) {
+                    super.onPostExecute(aVoid);
+                    mAdapterList.clear();
+                    mAdapterList.addAll(mNewList);
+                    mAdapter.notifyDataSetChanged();
+                }
+            };
         }
     }
 
@@ -1390,5 +1522,51 @@ public class SearchActivity extends Activity
     public void onNothingSelected(AdapterView<?> adapterView) {
         //ignore
     }
+
+    /**
+     * A class that holds the full data information.
+     */
+    public static class DataHolder {
+        private SearchResult mSearchResult;
+        Drawable mDwIcon;
+        CharSequence mName;
+        String mParentDir;
+        Float mRelevance;
+        MimeTypeCategory mMimeTypeCategory;
+
+        public DataHolder(SearchResult result, Drawable icon, CharSequence name, String parentDir,
+                          Float revelence, MimeTypeCategory category) {
+            mSearchResult = result;
+            mDwIcon = icon;
+            mName = name;
+            mParentDir = parentDir;
+            mRelevance = revelence;
+            mMimeTypeCategory = category;
+        }
+
+        public SearchResult getSearchResult() {
+            return mSearchResult;
+        }
+
+        public Drawable getDwIcon() {
+            return mDwIcon;
+        }
+
+        public CharSequence getName() {
+            return mName;
+        }
+
+        public String getParentDir() {
+            return mParentDir;
+        }
+
+        public Float getRelevance() {
+            return mRelevance;
+        }
+
+        public MimeTypeCategory getMimeTypeCategory() {
+            return mMimeTypeCategory;
+        }
+    }
 }
 
index 7cde6d6..92c73db 100644 (file)
@@ -18,6 +18,7 @@ package com.cyanogenmod.filemanager.adapters;
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
 import android.os.Handler;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
@@ -29,6 +30,7 @@ import android.widget.TextView;
 
 import com.cyanogenmod.filemanager.FileManagerApplication;
 import com.cyanogenmod.filemanager.R;
+import com.cyanogenmod.filemanager.activities.SearchActivity;
 import com.cyanogenmod.filemanager.model.FileSystemObject;
 import com.cyanogenmod.filemanager.model.Query;
 import com.cyanogenmod.filemanager.model.SearchResult;
@@ -49,7 +51,6 @@ import com.cyanogenmod.filemanager.util.SearchHelper;
 
 import java.io.File;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
@@ -58,7 +59,7 @@ import java.util.Map;
 /**
  * An implementation of {@link ArrayAdapter} for display search results.
  */
-public class SearchResultAdapter extends ArrayAdapter<SearchResult> {
+public class SearchResultAdapter extends ArrayAdapter<SearchActivity.DataHolder> {
 
     //The resource of the item icon
     private static final int RESOURCE_ITEM_ICON = R.id.search_item_icon;
@@ -89,49 +90,26 @@ public class SearchResultAdapter extends ArrayAdapter<SearchResult> {
         TextView mMimeType;
     }
 
-    /**
-     * A class that holds the full data information.
-     */
-    private static class DataHolder {
-        /**
-         * @hide
-         */
-        public DataHolder() {
-            super();
-        }
-        Drawable mDwIcon;
-        CharSequence mName;
-        String mParentDir;
-        Float mRelevance;
-        MimeTypeHelper.MimeTypeCategory mimeTypeCategory;
-    }
-
     // delay for when the new items, if any, will be incorporated
     // used to ensure that UI remains responsive
     private final int STREAMING_MODE_REFRESH_DELAY = 500;   // in ms
 
-    private DataHolder[] mData;
     private IconHolder mIconHolder;
     private final int mItemViewResourceId;
 
-    private final boolean mHighlightTerms;
-    private final boolean mShowRelevanceWidget;
-
     private final List<String> mQueries;
-    private final List<SearchResult> mOriginalList;
 
     private boolean mDisposed;
 
     private Handler mHandler;
     private boolean mInStreamingMode;
-    private List<SearchResult> mNewItems = new ArrayList<SearchResult>();
     private SearchSortResultMode mSearchSortResultMode;
-    private Comparator<SearchResult> mSearchResultComparator;
+    private Comparator<SearchActivity.DataHolder> mSearchResultComparator;
 
     private Runnable mParseNewResults = new Runnable() {
         @Override
         public void run() {
-            addPendingSearchResults();
+            sort(mSearchResultComparator);
             if (mInStreamingMode) {
                 mHandler.postDelayed(mParseNewResults, STREAMING_MODE_REFRESH_DELAY);
             }
@@ -148,35 +126,18 @@ public class SearchResultAdapter extends ArrayAdapter<SearchResult> {
      * @param queries The query object used to make the result of this search
      */
     public SearchResultAdapter(
-            Context context, List<SearchResult> files, int itemViewResourceId, Query queries) {
+            Context context, List<SearchActivity.DataHolder> files, int itemViewResourceId,
+            Query queries, IconHolder iconHolder) {
         super(context, RESOURCE_ITEM_NAME, files);
         mHandler = new Handler(context.getMainLooper());
-        mOriginalList = new ArrayList<SearchResult>(files);
 
         this.mDisposed = false;
-        final boolean displayThumbs = Preferences.getSharedPreferences().getBoolean(
-                FileManagerSettings.SETTINGS_DISPLAY_THUMBS.getId(),
-                ((Boolean)FileManagerSettings.SETTINGS_DISPLAY_THUMBS.getDefaultValue()).booleanValue());
-        this.mIconHolder = new IconHolder(context, displayThumbs);
+        this.mIconHolder = iconHolder;
         this.mItemViewResourceId = itemViewResourceId;
         this.mQueries = queries.getQueries();
 
-        // Load settings
-        this.mHighlightTerms = Preferences.getSharedPreferences().getBoolean(
-                FileManagerSettings.SETTINGS_HIGHLIGHT_TERMS.getId(),
-                ((Boolean)FileManagerSettings.SETTINGS_HIGHLIGHT_TERMS.
-                        getDefaultValue()).booleanValue());
-        this.mShowRelevanceWidget = Preferences.getSharedPreferences().getBoolean(
-                FileManagerSettings.SETTINGS_SHOW_RELEVANCE_WIDGET.getId(),
-                ((Boolean)FileManagerSettings.SETTINGS_SHOW_RELEVANCE_WIDGET.
-                        getDefaultValue()).booleanValue());
-
         // determine the sort order of search results
         setSortResultMode();
-
-        //Do cache of the data for better performance
-        loadDefaultIcons();
-        processData();
     }
 
     /**
@@ -198,14 +159,6 @@ public class SearchResultAdapter extends ArrayAdapter<SearchResult> {
     }
 
     /**
-     * Method that loads the default icons (known icons and more common icons).
-     */
-    private void loadDefaultIcons() {
-        this.mIconHolder.getDrawable("ic_fso_folder_drawable"); //$NON-NLS-1$
-        this.mIconHolder.getDrawable("ic_fso_default_drawable"); //$NON-NLS-1$
-    }
-
-    /**
      * {@inheritDoc}
      */
     @Override
@@ -213,31 +166,25 @@ public class SearchResultAdapter extends ArrayAdapter<SearchResult> {
         if (this.mDisposed) {
             return;
         }
-        processData();
         super.notifyDataSetChanged();
     }
 
+
     /**
      * Adds a new Search Result to the buffer
      */
-    public synchronized void addNewItem(SearchResult newResult) {
-        mNewItems.add(newResult);
+    public void addNewItem(SearchActivity.DataHolder data) {
+        if (mDisposed) {
+            return;
+        }
+
+        add(data);
     }
 
     /**
      * Adds search results in the buffer to the adapter list
      */
     public synchronized void addPendingSearchResults() {
-        if (mNewItems.size() < 1) return;
-
-        // TODO: maintain a sorted buffer and implement Merge of two sorted lists
-        addAll(mNewItems);
-        sort(mSearchResultComparator);
-        mOriginalList.addAll(mNewItems);    // cache files so enable mime type filtering later on
-        Collections.sort(mOriginalList, mSearchResultComparator);
-
-        // reset buffer
-        mNewItems.clear();
     }
 
     /**
@@ -252,19 +199,20 @@ public class SearchResultAdapter extends ArrayAdapter<SearchResult> {
         mSearchSortResultMode = SearchSortResultMode.fromId(currValue);
 
         if (mSearchSortResultMode.compareTo(SearchSortResultMode.NAME) == 0) {
-            mSearchResultComparator = new Comparator<SearchResult>() {
+            mSearchResultComparator = new Comparator<SearchActivity.DataHolder>() {
                 @Override
-                public int compare(SearchResult lhs, SearchResult rhs) {
+                public int compare(SearchActivity.DataHolder lhs, SearchActivity.DataHolder rhs) {
                     return FileHelper.doCompare(
-                            lhs.getFso(), rhs.getFso(), NavigationSortMode.NAME_ASC);
+                            lhs.getSearchResult().getFso(), rhs.getSearchResult().getFso(),
+                            NavigationSortMode.NAME_ASC);
                 }
             };
 
         } else if (mSearchSortResultMode.compareTo(SearchSortResultMode.RELEVANCE) == 0) {
-            mSearchResultComparator = new Comparator<SearchResult>() {
+            mSearchResultComparator = new Comparator<SearchActivity.DataHolder>() {
                 @Override
-                public int compare(SearchResult lhs, SearchResult rhs) {
-                    return lhs.compareTo(rhs);
+                public int compare(SearchActivity.DataHolder lhs, SearchActivity.DataHolder rhs) {
+                    return lhs.getSearchResult().compareTo(rhs.getSearchResult());
                 }
             };
         }
@@ -274,39 +222,7 @@ public class SearchResultAdapter extends ArrayAdapter<SearchResult> {
      * Size of the search results list
      */
     public synchronized int resultsSize() {
-        return getCount() + mNewItems.size();
-    }
-
-    /**
-     * Method that allows filtering the results by {@link MimeTypeHelper.MimeTypeCategory}
-     * @param mimeFilter the MimeTypeCategory to filter by
-     */
-    public void setMimeFilter(String mimeFilter) {
-        // Are we in ChRooted environment?
-        boolean chRooted =
-                FileManagerApplication.getAccessMode().compareTo(AccessMode.SAFE) == 0;
-
-        // Create display restrictions
-        Map<DisplayRestrictions, Object> restrictions =
-                new HashMap<DisplayRestrictions, Object>();
-        restrictions.put(
-                DisplayRestrictions.MIME_TYPE_RESTRICTION, MimeTypeHelper.ALL_MIME_TYPES);
-
-        List<SearchResult> newResults = SearchHelper.convertToResults(
-                FileHelper.applyUserPreferences(
-                        getFiles(), restrictions, true, chRooted), new Query().fillSlots(mQueries));
-
-        clear();
-        for (SearchResult result : newResults) {
-            // Only show results that are within our category, or all if no filter is set
-            if (TextUtils.equals(mimeFilter, MimeTypeHelper.MimeTypeCategory.NONE.name()) ||
-                    MimeTypeHelper.getCategory(getContext(), result.getFso()) ==
-                            MimeTypeHelper.MimeTypeCategory.valueOf(mimeFilter)) {
-                add(result);
-            }
-        }
-
-        this.notifyDataSetChanged();
+        return getCount();
     }
 
     /**
@@ -318,49 +234,10 @@ public class SearchResultAdapter extends ArrayAdapter<SearchResult> {
         }
         this.mDisposed = true;
         clear();
-        this.mOriginalList.clear();
-        this.mData = null;
         this.mIconHolder = null;
     }
 
     /**
-     * Method that process the data before use {@link #getView} method.
-     */
-    private void processData() {
-        Theme theme = ThemeManager.getCurrentTheme(getContext());
-        int highlightedColor =
-                theme.getColor(getContext(), "search_highlight_color"); //$NON-NLS-1$
-
-        this.mData = new DataHolder[getCount()];
-        int cc = getCount();
-        for (int i = 0; i < cc; i++) {
-            //File system object info
-            SearchResult result = getItem(i);
-
-            //Build the data holder
-            final FileSystemObject fso = result.getFso();
-            this.mData[i] = new SearchResultAdapter.DataHolder();
-            this.mData[i].mDwIcon = this.mIconHolder.getDrawable(
-                    MimeTypeHelper.getIcon(getContext(), fso));
-            if (this.mHighlightTerms) {
-                this.mData[i].mName =
-                        SearchHelper.getHighlightedName(result, this.mQueries, highlightedColor);
-            } else {
-                this.mData[i].mName = SearchHelper.getNonHighlightedName(result);
-            }
-            this.mData[i].mParentDir = new File(result.getFso().getFullPath()).getParent();
-            if (this.mShowRelevanceWidget) {
-                this.mData[i].mRelevance =
-                        Float.valueOf(
-                                (float)(result.getRelevance() * 100) / SearchResult.MAX_RELEVANCE);
-            } else {
-                this.mData[i].mRelevance = null;
-            }
-            this.mData[i].mimeTypeCategory = MimeTypeHelper.getCategory(getContext(), fso);
-        }
-    }
-
-    /**
      * Method that returns the data of the adapter.
      *
      * @return List<SearchResult> The adapter data
@@ -369,7 +246,7 @@ public class SearchResultAdapter extends ArrayAdapter<SearchResult> {
         int cc = getCount();
         final List<SearchResult> data = new ArrayList<SearchResult>(cc);
         for (int i = 0; i < cc; i++) {
-            data.add(getItem(i));
+            data.add(getItem(i).getSearchResult());
         }
         return data;
     }
@@ -381,8 +258,9 @@ public class SearchResultAdapter extends ArrayAdapter<SearchResult> {
      */
     public List<FileSystemObject> getFiles()  {
         final List<FileSystemObject> data = new ArrayList<FileSystemObject>();
-        for (SearchResult result : mOriginalList) {
-            data.add(result.getFso());
+        int N = getCount();
+        for(int i = 0; i < N; i++) {
+            data.add(getItem(i).getSearchResult().getFso());
         }
         return data;
     }
@@ -396,7 +274,7 @@ public class SearchResultAdapter extends ArrayAdapter<SearchResult> {
     public int getPosition(FileSystemObject item) {
         int cc = getCount();
         for (int i = 0; i < cc; i++) {
-            SearchResult sr = getItem(i);
+            SearchResult sr = getItem(i).getSearchResult();
             if (sr.getFso().compareTo(item) == 0) {
                 return i;
             }
@@ -437,25 +315,25 @@ public class SearchResultAdapter extends ArrayAdapter<SearchResult> {
         }
 
         //Retrieve data holder
-        final DataHolder dataHolder = this.mData[position];
+        final SearchActivity.DataHolder dataHolder = getItem(position);
 
         //Retrieve the view holder
         ViewHolder viewHolder = (ViewHolder) v.getTag();
 
         //Set the data
         mIconHolder.loadDrawable(viewHolder.mIvIcon,
-                getItem(position).getFso(), dataHolder.mDwIcon);
+                dataHolder.getSearchResult().getFso(), dataHolder.getDwIcon());
 
-        viewHolder.mTvName.setText(dataHolder.mName, TextView.BufferType.SPANNABLE);
-        viewHolder.mTvParentDir.setText(dataHolder.mParentDir);
-        if (dataHolder.mRelevance != null) {
-            viewHolder.mWgRelevance.setRelevance(dataHolder.mRelevance.floatValue());
+        viewHolder.mTvName.setText(dataHolder.getName(), TextView.BufferType.SPANNABLE);
+        viewHolder.mTvParentDir.setText(dataHolder.getParentDir());
+        if (dataHolder.getRelevance() != null) {
+            viewHolder.mWgRelevance.setRelevance(dataHolder.getRelevance().floatValue());
         }
         viewHolder.mWgRelevance.setVisibility(
-                dataHolder.mRelevance != null ? View.VISIBLE : View.GONE);
-        if (dataHolder.mimeTypeCategory != MimeTypeHelper.MimeTypeCategory.NONE) {
+                dataHolder.getRelevance() != null ? View.VISIBLE : View.GONE);
+        if (dataHolder.getMimeTypeCategory() != MimeTypeHelper.MimeTypeCategory.NONE) {
             viewHolder.mMimeType.setVisibility(View.VISIBLE);
-            viewHolder.mMimeType.setText(dataHolder.mimeTypeCategory.name());
+            viewHolder.mMimeType.setText(dataHolder.getMimeTypeCategory().name());
         } else {
             viewHolder.mMimeType.setVisibility(View.GONE);
         }