Async folder loading. Optimized search result loading.
This commit is contained in:
parent
6749661b0b
commit
6f0d39a457
2 changed files with 123 additions and 46 deletions
|
|
@ -3,7 +3,6 @@ package com.kabouzeid.gramophone.ui.activities;
|
|||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v4.view.MenuItemCompat;
|
||||
|
|
@ -11,6 +10,7 @@ import android.support.v7.widget.LinearLayoutManager;
|
|||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.SearchView;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
|
|
@ -33,9 +33,11 @@ import java.util.List;
|
|||
|
||||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import hugo.weaving.DebugLog;
|
||||
|
||||
public class SearchActivity extends AbsMusicServiceActivity implements SearchView.OnQueryTextListener, LoaderManager.LoaderCallbacks<List<Object>> {
|
||||
public static final String TAG = SearchActivity.class.getSimpleName();
|
||||
public static final String QUERY = "query";
|
||||
private static final int LOADER_ID = 1;
|
||||
|
||||
@Bind(R.id.recycler_view)
|
||||
|
|
@ -48,7 +50,9 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
|
|||
SearchView searchView;
|
||||
|
||||
private SearchAdapter adapter;
|
||||
private String query;
|
||||
|
||||
@DebugLog
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
|
@ -81,9 +85,24 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
|
|||
|
||||
setUpToolBar();
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
query = savedInstanceState.getString(QUERY);
|
||||
}
|
||||
|
||||
getSupportLoaderManager().initLoader(LOADER_ID, null, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putString(QUERY, query);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
}
|
||||
|
||||
private void setUpToolBar() {
|
||||
toolbar.setBackgroundColor(ThemeStore.primaryColor(this));
|
||||
setSupportActionBar(toolbar);
|
||||
|
|
@ -91,6 +110,7 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
|
|||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
@DebugLog
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_search, menu);
|
||||
|
|
@ -98,7 +118,7 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
|
|||
final MenuItem searchItem = menu.findItem(R.id.search);
|
||||
searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
|
||||
searchView.setQueryHint(getString(R.string.search_hint));
|
||||
searchView.setOnQueryTextListener(this);
|
||||
searchView.setMaxWidth(Integer.MAX_VALUE);
|
||||
|
||||
MenuItemCompat.expandActionView(searchItem);
|
||||
MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() {
|
||||
|
|
@ -114,6 +134,14 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
|
|||
}
|
||||
});
|
||||
|
||||
searchView.setQuery(query, false);
|
||||
searchView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
searchView.setOnQueryTextListener(SearchActivity.this);
|
||||
}
|
||||
});
|
||||
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
|
|
@ -126,18 +154,14 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
|
|||
}
|
||||
|
||||
private void search(@NonNull String query) {
|
||||
Loader loader = getSupportLoaderManager().getLoader(LOADER_ID);
|
||||
AsyncSearchResultLoader asyncSearchResultLoader = (AsyncSearchResultLoader) loader;
|
||||
asyncSearchResultLoader.setQuery(query);
|
||||
asyncSearchResultLoader.forceLoad();
|
||||
this.query = query;
|
||||
getSupportLoaderManager().restartLoader(LOADER_ID, null, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaStoreChanged() {
|
||||
super.onMediaStoreChanged();
|
||||
Loader loader = getSupportLoaderManager().getLoader(LOADER_ID);
|
||||
AsyncSearchResultLoader asyncSearchResultLoader = (AsyncSearchResultLoader) loader;
|
||||
asyncSearchResultLoader.forceLoad();
|
||||
getSupportLoaderManager().restartLoader(LOADER_ID, null, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -146,6 +170,7 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
|
|||
return false;
|
||||
}
|
||||
|
||||
@DebugLog
|
||||
@Override
|
||||
public boolean onQueryTextChange(String newText) {
|
||||
search(newText);
|
||||
|
|
@ -161,7 +186,7 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
|
|||
|
||||
@Override
|
||||
public Loader<List<Object>> onCreateLoader(int id, Bundle args) {
|
||||
return new AsyncSearchResultLoader(this);
|
||||
return new AsyncSearchResultLoader(this, query);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -175,21 +200,17 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
|
|||
}
|
||||
|
||||
private static class AsyncSearchResultLoader extends WrappedAsyncTaskLoader<List<Object>> {
|
||||
private String query;
|
||||
private final String query;
|
||||
|
||||
public AsyncSearchResultLoader(Context context) {
|
||||
public AsyncSearchResultLoader(Context context, String query) {
|
||||
super(context);
|
||||
setUpdateThrottle(200);
|
||||
}
|
||||
|
||||
public void setQuery(@Nullable String query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> loadInBackground() {
|
||||
List<Object> results = new ArrayList<>();
|
||||
if (query != null && !query.trim().equals("")) {
|
||||
if (!TextUtils.isEmpty(query)) {
|
||||
List songs = SongLoader.getSongs(getContext(), query);
|
||||
if (!songs.isEmpty()) {
|
||||
results.add(getContext().getResources().getString(R.string.songs));
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ import android.support.annotation.Nullable;
|
|||
import android.support.design.widget.AppBarLayout;
|
||||
import android.support.design.widget.CoordinatorLayout;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
|
|
@ -39,6 +41,7 @@ import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
|||
import com.kabouzeid.gramophone.interfaces.CabHolder;
|
||||
import com.kabouzeid.gramophone.loader.SongLoader;
|
||||
import com.kabouzeid.gramophone.loader.SortedCursor;
|
||||
import com.kabouzeid.gramophone.misc.WrappedAsyncTaskLoader;
|
||||
import com.kabouzeid.gramophone.model.Song;
|
||||
import com.kabouzeid.gramophone.ui.activities.MainActivity;
|
||||
import com.kabouzeid.gramophone.ui.fragments.mainactivity.AbsMainActivityFragment;
|
||||
|
|
@ -51,6 +54,7 @@ import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView;
|
|||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
|
@ -61,9 +65,11 @@ import java.util.List;
|
|||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class FoldersFragment extends AbsMainActivityFragment implements MainActivity.MainActivityFragmentCallbacks, CabHolder, BreadCrumbLayout.SelectionCallback, SongFileAdapter.Callbacks, AppBarLayout.OnOffsetChangedListener {
|
||||
public class FoldersFragment extends AbsMainActivityFragment implements MainActivity.MainActivityFragmentCallbacks, CabHolder, BreadCrumbLayout.SelectionCallback, SongFileAdapter.Callbacks, AppBarLayout.OnOffsetChangedListener, LoaderManager.LoaderCallbacks<List<File>> {
|
||||
public static final String TAG = FoldersFragment.class.getSimpleName();
|
||||
|
||||
private static final int LOADER_ID = 1;
|
||||
|
||||
protected static final String PATH = "path";
|
||||
protected static final String CRUMBS = "crumbs";
|
||||
|
||||
|
|
@ -101,43 +107,41 @@ public class FoldersFragment extends AbsMainActivityFragment implements MainActi
|
|||
}
|
||||
|
||||
public void setCrumb(BreadCrumbLayout.Crumb crumb, boolean addToHistory) {
|
||||
if (crumb == null) return;
|
||||
saveScrollPosition();
|
||||
updateAdapter(crumb.getFile());
|
||||
breadCrumbs.setActiveOrAdd(crumb, false);
|
||||
if (addToHistory)
|
||||
if (addToHistory) {
|
||||
breadCrumbs.addHistory(crumb);
|
||||
crumb = breadCrumbs.findCrumb(crumb.getFile()); // get the real reference so we can restore previous scroll states
|
||||
((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(crumb.getScrollPosition(), 0);
|
||||
}
|
||||
getLoaderManager().restartLoader(LOADER_ID, null, this);
|
||||
}
|
||||
|
||||
private void saveScrollPosition() {
|
||||
if (breadCrumbs.size() > 0) {
|
||||
BreadCrumbLayout.Crumb crumb = breadCrumbs.getCrumb(breadCrumbs.getActiveIndex());
|
||||
BreadCrumbLayout.Crumb crumb = getActiveCrumb();
|
||||
if (crumb != null) {
|
||||
crumb.setScrollPosition(((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private BreadCrumbLayout.Crumb getActiveCrumb() {
|
||||
return breadCrumbs != null && breadCrumbs.size() > 0 ? breadCrumbs.getCrumb(breadCrumbs.getActiveIndex()) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putParcelable(CRUMBS, breadCrumbs.getStateWrapper());
|
||||
}
|
||||
|
||||
private void updateAdapter(File directory) {
|
||||
List<File> files = sort(listFiles(directory, getFileFilter()));
|
||||
if (adapter == null) {
|
||||
adapter = new SongFileAdapter(getMainActivity(), files, R.layout.item_list, this, this);
|
||||
adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
|
||||
@Override
|
||||
public void onChanged() {
|
||||
super.onChanged();
|
||||
checkIsEmpty();
|
||||
}
|
||||
});
|
||||
recyclerView.setAdapter(adapter);
|
||||
checkIsEmpty();
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
if (savedInstanceState == null) {
|
||||
setCrumb(new BreadCrumbLayout.Crumb(tryGetCanonicalFile((File) getArguments().getSerializable(PATH))), true);
|
||||
} else {
|
||||
adapter.swapDataSet(files);
|
||||
breadCrumbs.restoreFromStateWrapper((BreadCrumbLayout.SavedStateWrapper) savedInstanceState.getParcelable(CRUMBS));
|
||||
getLoaderManager().initLoader(LOADER_ID, null, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -158,13 +162,7 @@ public class FoldersFragment extends AbsMainActivityFragment implements MainActi
|
|||
setUpToolbar();
|
||||
setUpBreadCrumbs();
|
||||
setUpRecyclerView();
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
setCrumb(new BreadCrumbLayout.Crumb(tryGetCanonicalFile((File) getArguments().getSerializable(PATH))), true);
|
||||
} else {
|
||||
breadCrumbs.restoreFromStateWrapper((BreadCrumbLayout.SavedStateWrapper) savedInstanceState.getParcelable(CRUMBS));
|
||||
setCrumb(breadCrumbs.getCrumb(breadCrumbs.getActiveIndex()), true);
|
||||
}
|
||||
setUpAdapter();
|
||||
}
|
||||
|
||||
private void setUpAppbarColor() {
|
||||
|
|
@ -194,6 +192,19 @@ public class FoldersFragment extends AbsMainActivityFragment implements MainActi
|
|||
appbar.addOnOffsetChangedListener(this);
|
||||
}
|
||||
|
||||
private void setUpAdapter() {
|
||||
adapter = new SongFileAdapter(getMainActivity(), new LinkedList<File>(), R.layout.item_list, this, this);
|
||||
adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
|
||||
@Override
|
||||
public void onChanged() {
|
||||
super.onChanged();
|
||||
checkIsEmpty();
|
||||
}
|
||||
});
|
||||
recyclerView.setAdapter(adapter);
|
||||
checkIsEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
|
@ -463,7 +474,7 @@ public class FoldersFragment extends AbsMainActivityFragment implements MainActi
|
|||
}
|
||||
|
||||
@NonNull
|
||||
private List<File> listFiles(@NonNull File directory, @Nullable FileFilter fileFilter) {
|
||||
private static List<File> listFiles(@NonNull File directory, @Nullable FileFilter fileFilter) {
|
||||
List<File> fileList = new LinkedList<>();
|
||||
File[] found = directory.listFiles(fileFilter);
|
||||
if (found != null) {
|
||||
|
|
@ -605,4 +616,49 @@ public class FoldersFragment extends AbsMainActivityFragment implements MainActi
|
|||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAdapter(@NonNull List<File> files) {
|
||||
adapter.swapDataSet(files);
|
||||
BreadCrumbLayout.Crumb crumb = getActiveCrumb();
|
||||
if (crumb != null && recyclerView != null) {
|
||||
((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(crumb.getScrollPosition(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<List<File>> onCreateLoader(int id, Bundle args) {
|
||||
return new AsyncFileLoader(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<List<File>> loader, List<File> data) {
|
||||
updateAdapter(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<List<File>> loader) {
|
||||
updateAdapter(new LinkedList<File>());
|
||||
}
|
||||
|
||||
private static class AsyncFileLoader extends WrappedAsyncTaskLoader<List<File>> {
|
||||
private WeakReference<FoldersFragment> fragmentWeakReference;
|
||||
|
||||
public AsyncFileLoader(FoldersFragment foldersFragment) {
|
||||
super(foldersFragment.getActivity());
|
||||
fragmentWeakReference = new WeakReference<>(foldersFragment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<File> loadInBackground() {
|
||||
FoldersFragment foldersFragment = fragmentWeakReference.get();
|
||||
File directory = null;
|
||||
if (foldersFragment != null) {
|
||||
BreadCrumbLayout.Crumb crumb = foldersFragment.getActiveCrumb();
|
||||
if (crumb != null) {
|
||||
directory = crumb.getFile();
|
||||
}
|
||||
}
|
||||
return directory != null ? foldersFragment.sort(listFiles(directory, foldersFragment.getFileFilter())) : new LinkedList<File>();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue