use rxjava and debounce operation to perform search

This commit is contained in:
David Luhmer 2018-07-12 14:25:57 +02:00
parent 3638f4684c
commit 218e47afea
3 changed files with 179 additions and 140 deletions

View file

@ -29,11 +29,12 @@ import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.support.annotation.MainThread;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
@ -42,12 +43,12 @@ import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.Toast;
import org.apache.commons.lang3.time.StopWatch;
@ -64,6 +65,8 @@ import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm.SORT_DIRECTIO
import de.luhmer.owncloudnewsreader.database.model.RssItem;
import de.luhmer.owncloudnewsreader.database.model.RssItemDao;
import de.luhmer.owncloudnewsreader.helper.AsyncTaskHelper;
import de.luhmer.owncloudnewsreader.helper.Search;
import io.reactivex.observers.DisposableObserver;
/**
* A fragment representing a single NewsReader detail screen. This fragment is
@ -108,8 +111,6 @@ public class NewsReaderDetailFragment extends Fragment {
private int onResumeCount = 0;
private static final String LAYOUT_MANAGER_STATE = "LAYOUT_MANAGER_STATE";
private static final String SEARCH_IN_TITLE = "0";
private static final String SEARCH_IN_BODY = "1";
private boolean mMarkAsReadWhileScrollingEnabled;
@BindView(R.id.pb_loading) ProgressBar pbLoading;
@ -244,15 +245,6 @@ public class NewsReaderDetailFragment extends Fragment {
AsyncTaskHelper.StartAsyncTask(new UpdateCurrentRssViewTask(context));
}
/**
*
* @param context Context
* @param searchString The string to search for
*/
public void searchInCurrentRssView(final Context context, final String searchString) {
Log.v(TAG, "SearchInCurrentRssView");
AsyncTaskHelper.StartAsyncTask(new SearchInCurrentRssViewTask(context, searchString));
}
public RecyclerView getRecyclerView() {
return recyclerView;
@ -263,34 +255,60 @@ public class NewsReaderDetailFragment extends Fragment {
return (LinearLayoutManager) recyclerView.getLayoutManager();
}
protected List<RssItem> performSearch(String searchString) {
Handler mainHandler = new Handler(getActivity().getMainLooper());
Runnable myRunnable = new Runnable() {
@Override
public void run() {
pbLoading.setVisibility(View.VISIBLE);
tvNoItemsAvailable.setVisibility(View.GONE);
}
};
mainHandler.post(myRunnable);
return Search.PerformSearch(getActivity(), idFolder, idFeed, searchString);
}
protected DisposableObserver<List<RssItem>> SearchResultObserver = new DisposableObserver<List<RssItem>>() {
@Override
public void onNext(List<RssItem> rssItems) {
loadRssItemsIntoView(rssItems);
}
@Override
public void onError(Throwable e) {
Toast.makeText(getActivity(), e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
}
@Override
public void onComplete() {
Log.v(TAG, "Search Completed!");
}
};
private class UpdateCurrentRssViewTask extends AsyncTask<Void, Void, List<RssItem>> {
private Context context;
protected SORT_DIRECTION sortDirection;
public UpdateCurrentRssViewTask(Context context) {
UpdateCurrentRssViewTask(Context context) {
this.context = context;
}
protected Context getContext() {
return context;
}
@Override
protected void onPreExecute() {
pbLoading.setVisibility(View.VISIBLE);
tvNoItemsAvailable.setVisibility(View.GONE);
sortDirection = getSortDirection(context);
super.onPreExecute();
}
@Override
protected List<RssItem> doInBackground(Void... urls) {
protected List<RssItem> doInBackground(Void... voids) {
DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(context);
SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
SORT_DIRECTION sortDirection = getSortDirection(context);
boolean onlyUnreadItems = mPrefs.getBoolean(SettingsActivity.CB_SHOWONLYUNREAD_STRING, false);
boolean onlyStarredItems = false;
if (idFolder != null)
@ -327,113 +345,34 @@ public class NewsReaderDetailFragment extends Fragment {
@Override
protected void onPostExecute(List<RssItem> rssItem) {
try
{
NewsListRecyclerAdapter nra = ((NewsListRecyclerAdapter) recyclerView.getAdapter());
if(nra == null) {
nra = new NewsListRecyclerAdapter(getActivity(), recyclerView, (PodcastFragmentActivity) getActivity());
recyclerView.setAdapter(nra);
}
nra.updateAdapterData(rssItem);
pbLoading.setVisibility(View.GONE);
if(nra.getItemCount() <= 0) {
tvNoItemsAvailable.setVisibility(View.VISIBLE);
} else {
tvNoItemsAvailable.setVisibility(View.GONE);
}
recyclerView.scrollToPosition(0);
}
catch(Exception ex)
{
ex.printStackTrace();
}
loadRssItemsIntoView(rssItem);
}
}
private class SearchInCurrentRssViewTask extends UpdateCurrentRssViewTask {
void loadRssItemsIntoView(List<RssItem> rssItems) {
try {
NewsListRecyclerAdapter nra = ((NewsListRecyclerAdapter) recyclerView.getAdapter());
if (nra == null) {
nra = new NewsListRecyclerAdapter(getActivity(), recyclerView, (PodcastFragmentActivity) getActivity());
final private String searchString;
recyclerView.setAdapter(nra);
}
nra.updateAdapterData(rssItems);
/**
* Display only items in current view, where Title OR Body contain the searchString
* @param context Context
* @param searchString String to search for
*/
public SearchInCurrentRssViewTask(final Context context, final String searchString) {
super(context);
this.searchString=searchString;
}
@Override
protected List<RssItem> doInBackground(Void... urls) {
SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(super.getContext());
DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(super.getContext());
boolean onlyUnreadItems = mPrefs.getBoolean(SettingsActivity.CB_SHOWONLYUNREAD_STRING, false);
boolean onlyStarredItems = false;
String sqlSelectStatement = null;
if (idFeed != null) {
sqlSelectStatement = getFeedSQLStatement(idFeed, onlyUnreadItems, onlyStarredItems, sortDirection, searchString, dbConn, mPrefs);
} else if (idFolder != null) {
if (idFolder == SubscriptionExpandableListAdapter.SPECIAL_FOLDERS.ALL_STARRED_ITEMS.getValue()) {
onlyUnreadItems = false;
}
sqlSelectStatement = getFolderSQLStatement(idFolder, onlyUnreadItems, sortDirection,searchString, dbConn, mPrefs);
pbLoading.setVisibility(View.GONE);
if (nra.getItemCount() <= 0) {
tvNoItemsAvailable.setVisibility(View.VISIBLE);
} else {
tvNoItemsAvailable.setVisibility(View.GONE);
}
List<RssItem> items = null;
if (sqlSelectStatement != "") {
dbConn.insertIntoRssCurrentViewTable(sqlSelectStatement);
items = dbConn.getCurrentRssItemView(0);
}
return items;
recyclerView.scrollToPosition(0);
} catch (Exception ex) {
ex.printStackTrace();
}
private String getFeedSQLStatement(final long idFeed,
final boolean onlyUnreadItems,
final boolean onlyStarredItems,
final SORT_DIRECTION sort_direction,
final String searchString,
final DatabaseConnectionOrm dbConn,
final SharedPreferences mPrefs)
{
String sql="";
String searchIn = mPrefs.getString(SettingsActivity.SP_SEARCH_IN,"0");
if(searchIn.equals(SEARCH_IN_TITLE)) {
sql = dbConn.getAllItemsIdsForFeedSQLFilteredByTitle(idFeed, onlyUnreadItems, onlyStarredItems, sortDirection, searchString);
} else if(searchIn.equals(SEARCH_IN_BODY)) {
sql = dbConn.getAllItemsIdsForFeedSQLFilteredByBodySQL(idFeed, onlyUnreadItems, onlyStarredItems, sortDirection, searchString);
}
return sql;
}
private String getFolderSQLStatement(final long ID_FOLDER,
final boolean onlyUnreadItems,
final SORT_DIRECTION sort_direction,
final String searchString,
final DatabaseConnectionOrm dbConn,
final SharedPreferences mPrefs)
{
String sql="";
String searchIn = mPrefs.getString(SettingsActivity.SP_SEARCH_IN,"0");
if(searchIn.equals(SEARCH_IN_TITLE)) {
sql = dbConn.getAllItemsIdsForFolderSQLFilteredByTitle(ID_FOLDER, onlyUnreadItems, sortDirection, searchString);
} else if(searchIn.equals(SEARCH_IN_BODY)) {
sql = dbConn.getAllItemsIdsForFolderSQLFilteredByBody(ID_FOLDER, onlyUnreadItems, sortDirection, searchString);
}
return sql;
}
}
public static SORT_DIRECTION getSortDirection(Context context) {
return NewsDetailActivity.getSortDirectionFromSettings(context);
}

View file

@ -37,6 +37,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.annotation.MainThread;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
@ -48,7 +49,6 @@ import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v4.widget.ViewDragHelper;
@ -68,6 +68,7 @@ import org.greenrobot.eventbus.ThreadMode;
import java.lang.reflect.Field;
import java.util.List;
import java.util.concurrent.TimeUnit;
import butterknife.BindView;
import butterknife.ButterKnife;
@ -83,6 +84,7 @@ import de.luhmer.owncloudnewsreader.database.model.RssItem;
import de.luhmer.owncloudnewsreader.events.podcast.FeedPanelSlideEvent;
import de.luhmer.owncloudnewsreader.helper.DatabaseUtils;
import de.luhmer.owncloudnewsreader.helper.PostDelayHandler;
import de.luhmer.owncloudnewsreader.helper.Search;
import de.luhmer.owncloudnewsreader.helper.ThemeChooser;
import de.luhmer.owncloudnewsreader.reader.nextcloud.RssItemObservable;
import de.luhmer.owncloudnewsreader.services.DownloadImagesService;
@ -92,10 +94,15 @@ import de.luhmer.owncloudnewsreader.services.events.SyncFinishedEvent;
import de.luhmer.owncloudnewsreader.services.events.SyncStartedEvent;
import de.luhmer.owncloudnewsreader.ssl.OkHttpSSLClient;
import io.reactivex.Completable;
import io.reactivex.ObservableSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Action;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.observers.DisposableObserver;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.PublishSubject;
import uk.co.deanwild.materialshowcaseview.MaterialShowcaseSequence;
import uk.co.deanwild.materialshowcaseview.ShowcaseConfig;
@ -136,7 +143,9 @@ public class NewsReaderListActivity extends PodcastFragmentActivity implements
private ActionBarDrawerToggle drawerToggle;
private SearchView searchView;
@Override
private PublishSubject<String> searchPublishSubject;
@Override
protected void onCreate(Bundle savedInstanceState) {
ThemeChooser.ChooseTheme(this);
super.onCreate(savedInstanceState);
@ -379,7 +388,7 @@ public class NewsReaderListActivity extends PodcastFragmentActivity implements
super.onStart();
}
@Override
@Override
protected void onStop() {
unbindService(mConnection);
mConnection = null;
@ -792,17 +801,6 @@ public class NewsReaderListActivity extends PodcastFragmentActivity implements
return super.onOptionsItemSelected(item);
}
private void StartSearch(final String searchString) {
NewsReaderDetailFragment ndf = getNewsReaderDetailFragment();
if(ndf != null)
{
ndf.searchInCurrentRssView(this,searchString);
}
}
private void DownloadMoreItems()
{
String username = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getString("edt_username", null);
@ -969,12 +967,30 @@ public class NewsReaderListActivity extends PodcastFragmentActivity implements
@Override
public boolean onQueryTextChange(String newText) {
StartSearch(newText);
return true;
}
if (searchPublishSubject == null) {
searchPublishSubject = PublishSubject.create();
searchPublishSubject
.debounce(300, TimeUnit.MILLISECONDS)
.distinctUntilChanged()
.map(new Function<String, List<RssItem>>() {
public void clearSearchViewFocus() {
searchView.clearFocus();
}
@Override
public List<RssItem> apply(String s) throws Exception {
return getNewsReaderDetailFragment().performSearch(s);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(getNewsReaderDetailFragment().SearchResultObserver)
.isDisposed();
}
searchPublishSubject.onNext(newText);
return true;
}
public void clearSearchViewFocus() {
searchView.clearFocus();
}
}

View file

@ -0,0 +1,84 @@
package de.luhmer.owncloudnewsreader.helper;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import java.util.List;
import de.luhmer.owncloudnewsreader.ListView.SubscriptionExpandableListAdapter;
import de.luhmer.owncloudnewsreader.NewsDetailActivity;
import de.luhmer.owncloudnewsreader.SettingsActivity;
import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm;
import de.luhmer.owncloudnewsreader.database.model.RssItem;
public class Search {
private static final String SEARCH_IN_TITLE = "0";
private static final String SEARCH_IN_BODY = "1";
public static List<RssItem> PerformSearch(Context context, Long idFolder, Long idFeed, String searchString) {
DatabaseConnectionOrm.SORT_DIRECTION sortDirection = NewsDetailActivity.getSortDirectionFromSettings(context);
DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(context);
SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean onlyUnreadItems = mPrefs.getBoolean(SettingsActivity.CB_SHOWONLYUNREAD_STRING, false);
boolean onlyStarredItems = false;
String sqlSelectStatement = null;
if (idFeed != null) {
sqlSelectStatement = getFeedSQLStatement(idFeed, onlyUnreadItems, onlyStarredItems, sortDirection, searchString, dbConn, mPrefs);
} else if (idFolder != null) {
if (idFolder == SubscriptionExpandableListAdapter.SPECIAL_FOLDERS.ALL_STARRED_ITEMS.getValue()) {
onlyUnreadItems = false;
}
sqlSelectStatement = getFolderSQLStatement(idFolder, onlyUnreadItems, sortDirection, searchString, dbConn, mPrefs);
}
List<RssItem> items = null;
if (sqlSelectStatement != "") {
dbConn.insertIntoRssCurrentViewTable(sqlSelectStatement);
items = dbConn.getCurrentRssItemView(0);
}
return items;
}
private static String getFeedSQLStatement(final long idFeed,
final boolean onlyUnreadItems,
final boolean onlyStarredItems,
final DatabaseConnectionOrm.SORT_DIRECTION sortDirection,
final String searchString,
final DatabaseConnectionOrm dbConn,
final SharedPreferences mPrefs) {
String sql = "";
String searchIn = mPrefs.getString(SettingsActivity.SP_SEARCH_IN,"0");
if(searchIn.equals(SEARCH_IN_TITLE)) {
sql = dbConn.getAllItemsIdsForFeedSQLFilteredByTitle(idFeed, onlyUnreadItems, onlyStarredItems, sortDirection, searchString);
} else if(searchIn.equals(SEARCH_IN_BODY)) {
sql = dbConn.getAllItemsIdsForFeedSQLFilteredByBodySQL(idFeed, onlyUnreadItems, onlyStarredItems, sortDirection, searchString);
}
return sql;
}
private static String getFolderSQLStatement(final long ID_FOLDER,
final boolean onlyUnreadItems,
final DatabaseConnectionOrm.SORT_DIRECTION sortDirection,
final String searchString,
final DatabaseConnectionOrm dbConn,
final SharedPreferences mPrefs) {
String sql = "";
String searchIn = mPrefs.getString(SettingsActivity.SP_SEARCH_IN,"0");
if(searchIn.equals(SEARCH_IN_TITLE)) {
sql = dbConn.getAllItemsIdsForFolderSQLFilteredByTitle(ID_FOLDER, onlyUnreadItems, sortDirection, searchString);
} else if(searchIn.equals(SEARCH_IN_BODY)) {
sql = dbConn.getAllItemsIdsForFolderSQLFilteredByBody(ID_FOLDER, onlyUnreadItems, sortDirection, searchString);
}
return sql;
}
}