[Android] [PATCH] Threaded SQLite search

Geoffrey Métais geoffrey.metais at gmail.com
Wed Nov 26 14:27:29 CET 2014


---
 .../src/org/videolan/vlc/MediaDatabase.java        | 24 ++++++++++
 vlc-android/src/org/videolan/vlc/MediaLibrary.java | 11 +++++
 .../src/org/videolan/vlc/gui/SearchFragment.java   | 55 +++++++++-------------
 .../org/videolan/vlc/gui/tv/SearchFragment.java    | 41 ++++++++--------
 4 files changed, 76 insertions(+), 55 deletions(-)

diff --git a/vlc-android/src/org/videolan/vlc/MediaDatabase.java b/vlc-android/src/org/videolan/vlc/MediaDatabase.java
index bb701e4..b0ca809 100644
--- a/vlc-android/src/org/videolan/vlc/MediaDatabase.java
+++ b/vlc-android/src/org/videolan/vlc/MediaDatabase.java
@@ -343,6 +343,30 @@ public class MediaDatabase {
         return files;
     }
 
+    public synchronized ArrayList<String> searchMedia(String filter, int type){
+
+        ArrayList<String> mediaList = new ArrayList<String>();
+
+        String[] queryColumns = new String[]{MEDIA_LOCATION, MEDIA_TITLE, MEDIA_ALBUM, MEDIA_ARTIST, MEDIA_TYPE};
+        String queryString = MEDIA_TITLE+" LIKE ? OR "+MEDIA_ALBUM+" LIKE ? OR "+MEDIA_ARTIST+" LIKE ?";
+        String [] queryArgs;
+        if (type != Media.TYPE_ALL) {
+            queryString = "( " + queryString + " ) AND " + MEDIA_TYPE + "=?";
+            queryArgs = new String[]{"%"+filter+"%", "%"+filter+"%", "%"+filter+"%", String.valueOf(type)};
+        } else
+            queryArgs = new String[]{"%"+filter+"%", "%"+filter+"%", "%"+filter+"%"};
+
+        Cursor cursor = mDb.query(MEDIA_TABLE_NAME,
+                queryColumns, queryString, queryArgs, null, null, null, null);
+        if (cursor.moveToFirst()){
+            do {
+                mediaList.add(cursor.getString(0));
+            }while (cursor.moveToNext());
+            cursor.close();
+        }
+        return mediaList;
+    }
+
     public synchronized HashMap<String, Media> getMedias() {
 
         Cursor cursor;
diff --git a/vlc-android/src/org/videolan/vlc/MediaLibrary.java b/vlc-android/src/org/videolan/vlc/MediaLibrary.java
index 613239a..4a495bd 100644
--- a/vlc-android/src/org/videolan/vlc/MediaLibrary.java
+++ b/vlc-android/src/org/videolan/vlc/MediaLibrary.java
@@ -115,6 +115,17 @@ public class MediaLibrary {
         mUpdateHandler.remove(handler);
     }
 
+    public ArrayList<Media> searchMedia(String query, int type){
+        ArrayList<Media> mediaList = new ArrayList<Media>();
+        ArrayList<String> pathList = MediaDatabase.getInstance().searchMedia(query, type);
+        if (!pathList.isEmpty()){
+            for (String path : pathList) {
+                mediaList.add(getMediaItem(path));
+            }
+        }
+        return mediaList;
+    }
+
     public ArrayList<Media> getVideoItems() {
         ArrayList<Media> videoItems = new ArrayList<Media>();
         mItemListLock.readLock().lock();
diff --git a/vlc-android/src/org/videolan/vlc/gui/SearchFragment.java b/vlc-android/src/org/videolan/vlc/gui/SearchFragment.java
index 64a8d27..da8c950 100644
--- a/vlc-android/src/org/videolan/vlc/gui/SearchFragment.java
+++ b/vlc-android/src/org/videolan/vlc/gui/SearchFragment.java
@@ -21,7 +21,6 @@
 package org.videolan.vlc.gui;
 
 import java.util.ArrayList;
-import java.util.Locale;
 
 import org.videolan.libvlc.Media;
 import org.videolan.vlc.MediaDatabase;
@@ -32,6 +31,7 @@ import org.videolan.vlc.gui.video.VideoPlayerActivity;
 
 import android.content.Context;
 import android.os.Bundle;
+import android.os.Handler;
 import android.support.v4.app.ListFragment;
 import android.support.v7.app.ActionBarActivity;
 import android.text.Editable;
@@ -56,6 +56,8 @@ public class SearchFragment extends ListFragment {
     private SearchResultAdapter mResultAdapter;
     private LinearLayout mListHeader;
 
+    final private Handler mHandler = new Handler();
+
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle(R.string.search);
@@ -99,40 +101,27 @@ public class SearchFragment extends ListFragment {
         imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
     }
 
-    private void search(CharSequence key, int type) {
-
-        // set result adapter to the list
+    private void search(final String key, final int type) {
         mResultAdapter.clear();
-        String[] keys = key.toString().split("\\s+");
-        ArrayList<Media> allItems = MediaLibrary.getInstance().getMediaItems();
-        int results = 0;
-        for (int i = 0; i < allItems.size(); i++) {
-            Media item = allItems.get(i);
-            if (type != Media.TYPE_ALL && type != item.getType())
-                continue;
-            boolean add = true;
-            String name = item.getTitle().toLowerCase(Locale.getDefault());
-            String MRL = item.getLocation().toLowerCase(Locale.getDefault());
-            for (int k = 0; k < keys.length; k++) {
-                String s = keys[k].toLowerCase(Locale.getDefault());
-                if (!(name.contains(s) || MRL.contains(s))) {
-                    add = false;
-                    break;
-                }
-            }
-
-            if (add) {
-                mResultAdapter.add(item);
-                results++;
+        new Thread(new Runnable() {
+            public void run() {
+                final ArrayList<Media> mediaList = MediaLibrary.getInstance().searchMedia(key, type);
+                mHandler.post(new Runnable() {
+                    public void run() {
+                        int count = mediaList.size();
+                        for (int i = 0 ; i < count ; ++i)
+                            mResultAdapter.add(mediaList.get(i));
+                        mResultAdapter.sort();
+
+                        String headerText = getResources().getQuantityString(R.plurals.search_found_results_quantity, mediaList.size(), mediaList.size());
+                        showListHeader(headerText);
+
+                        setListAdapter(mResultAdapter);
+                    }
+                });
             }
+        }).start();
 
-        }
-        mResultAdapter.sort();
-
-        String headerText = getResources().getQuantityString(R.plurals.search_found_results_quantity, results, results);
-        showListHeader(headerText);
-
-        setListAdapter(mResultAdapter);
     }
 
     private void showListHeader(String text) {
@@ -169,7 +158,7 @@ public class SearchFragment extends ListFragment {
         @Override
         public void onTextChanged(CharSequence s, int start, int before, int count) {
             if (s.length() > 0) {
-                search(s, Media.TYPE_ALL);
+                search(s.toString(), Media.TYPE_ALL);
             } else {
                 showSearchHistory();
             }
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/SearchFragment.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/SearchFragment.java
index 5ce0799..e0be766 100644
--- a/vlc-android/tv/src/org/videolan/vlc/gui/tv/SearchFragment.java
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/SearchFragment.java
@@ -20,20 +20,14 @@
 package org.videolan.vlc.gui.tv;
 
 import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
 
 import org.videolan.libvlc.Media;
 import org.videolan.vlc.MediaLibrary;
 import org.videolan.vlc.R;
 
 import android.app.Activity;
-import android.content.Intent;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.Parcelable;
 import android.support.v17.leanback.widget.ArrayObjectAdapter;
 import android.support.v17.leanback.widget.HeaderItem;
 import android.support.v17.leanback.widget.ListRow;
@@ -47,7 +41,6 @@ public class SearchFragment extends android.support.v17.leanback.app.SearchFragm
 implements android.support.v17.leanback.app.SearchFragment.SearchResultProvider {
 
 	private static final String TAG = "SearchFragment";
-    private static final int SEARCH_DELAY_MS = 300;
 
     private ArrayObjectAdapter mRowsAdapter;
     private Handler mHandler = new Handler();
@@ -72,10 +65,10 @@ implements android.support.v17.leanback.app.SearchFragment.SearchResultProvider
 
     private void queryByWords(String words) {
         mRowsAdapter.clear();
-        if (!TextUtils.isEmpty(words)) {
+        if (!TextUtils.isEmpty(words) && words.length() > 2) {
             mDelayedLoad.setSearchQuery(words);
-            mHandler.removeCallbacks(mDelayedLoad);
-            mHandler.postDelayed(mDelayedLoad, SEARCH_DELAY_MS);
+            mDelayedLoad.setSearchType(Media.TYPE_ALL);
+            new Thread(mDelayedLoad).start();
         }
     }
 
@@ -91,18 +84,18 @@ implements android.support.v17.leanback.app.SearchFragment.SearchResultProvider
         return true;
     }
 
-    private void loadRows(String query) {
-        ArrayList<Media> mediaList = MediaLibrary.getInstance().getMediaItems();
-        ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new CardPresenter());
-        for (Media media : mediaList) {
-            if (media.getTitle().toLowerCase().indexOf(query.toLowerCase()) >= 0
-                    || media.getLocation().toLowerCase().indexOf(query.toLowerCase()) >= 0) {
-                listRowAdapter.add(media);
+    private void loadRows(String query, int type) {
+        ArrayList<Media> mediaList = MediaLibrary.getInstance().searchMedia(query, type);
+        final ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new CardPresenter());
+        listRowAdapter.addAll(0, mediaList);
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                HeaderItem header = new HeaderItem(0, getResources().getString(R.string.search_results),
+                        null);
+                mRowsAdapter.add(new ListRow(header, listRowAdapter));
             }
-        }
-        HeaderItem header = new HeaderItem(0, getResources().getString(R.string.search_results),
-                null);
-        mRowsAdapter.add(new ListRow(header, listRowAdapter));
+        });
     }
 
     protected OnItemClickedListener getDefaultItemClickedListener() {
@@ -119,15 +112,19 @@ implements android.support.v17.leanback.app.SearchFragment.SearchResultProvider
     private class SearchRunnable implements Runnable {
 
         private volatile String searchQuery;
+        private volatile int searchType;
 
         public SearchRunnable() {}
 
         public void run() {
-            loadRows(searchQuery);
+            loadRows(searchQuery, searchType);
         }
 
         public void setSearchQuery(String value) {
             this.searchQuery = value;
         }
+        public void setSearchType(int value) {
+            this.searchType = value;
+        }
     }
 }
-- 
1.9.1



More information about the Android mailing list