Clean up search fragment loader lifecycle.

- Programatically create SearchView to make it always expand across
  entire action bar.
- Store current query text during screen rotation
- Restart loader when query text changes

Bug: 33354491
Test: RunSettingsRoboTests
Change-Id: I63838a38514569aac60c5d67ac52ac06a7acd5a3
This commit is contained in:
Fan Zhang
2016-12-05 16:21:44 -08:00
parent 2425a528ad
commit 413eaa4070
9 changed files with 210 additions and 98 deletions

View File

@@ -16,107 +16,110 @@
package com.android.settings.search2;
import android.app.ActionBar;
import android.app.Activity;
import android.app.LoaderManager;
import android.content.Context;
import android.content.Loader;
import android.os.Bundle;
import android.app.LoaderManager;
import android.support.annotation.VisibleForTesting;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Menu;
import android.view.MenuInflater;
import android.widget.LinearLayout.LayoutParams;
import android.widget.SearchView;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.overlay.FeatureFactory;
import java.util.List;
public class SearchFragment extends InstrumentedFragment implements
SearchView.OnQueryTextListener, MenuItem.OnActionExpandListener,
LoaderManager.LoaderCallbacks<List<SearchResult>> {
SearchView.OnQueryTextListener, LoaderManager.LoaderCallbacks<List<SearchResult>> {
// State values
static final String STATE_QUERY = "query";
// Loader IDs
private static final int DATABASE_LOADER_ID = 0;
private SearchResultsAdapter mSearchAdapter;
@VisibleForTesting
String mQuery;
private SearchFeatureProvider mSearchFeatureProvider;
private DatabaseResultLoader mSearchLoader;
private SearchResultsAdapter mSearchAdapter;
private RecyclerView mResultsRecyclerView;
private SearchView mSearchView;
private MenuItem mSearchMenuItem;
private String mQuery;
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.DASHBOARD_SEARCH_RESULTS;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mSearchFeatureProvider = FeatureFactory.getFactory(context)
.getSearchFeatureProvider(context);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
mSearchAdapter = new SearchResultsAdapter();
final LoaderManager loaderManager = getLoaderManager();
loaderManager.initLoader(DATABASE_LOADER_ID, null, this);
if (savedInstanceState != null) {
mQuery = savedInstanceState.getString(STATE_QUERY);
getLoaderManager().initLoader(DATABASE_LOADER_ID, null, this);
}
final ActionBar actionBar = getActivity().getActionBar();
actionBar.setCustomView(makeSearchView(actionBar, mQuery));
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setDisplayShowTitleEnabled(false);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.search_panel_2, container, false);
mResultsRecyclerView = (RecyclerView) view.findViewById(R.id.list_results);
mResultsRecyclerView.setAdapter(mSearchAdapter);
mResultsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
return view;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.search_options_menu, menu);
mSearchMenuItem = menu.findItem(R.id.search);
mSearchView = (SearchView) mSearchMenuItem.getActionView();
mSearchView.setOnQueryTextListener(this);
mSearchView.setMaxWidth(Integer.MAX_VALUE);
mSearchMenuItem.expandActionView();
}
@Override
public boolean onMenuItemActionExpand(MenuItem item) {
return true;
}
@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
// Return false to prevent the search box from collapsing.
return false;
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(STATE_QUERY, mQuery);
}
@Override
public boolean onQueryTextChange(String query) {
if (query == null || query.equals(mQuery)) {
return false;
if (TextUtils.equals(query, mQuery)) {
return true;
}
mQuery = query;
clearLoaders();
mSearchAdapter.clearResults();
final LoaderManager loaderManager = getLoaderManager();
loaderManager.restartLoader(DATABASE_LOADER_ID, null, this);
if (TextUtils.isEmpty(mQuery)) {
getLoaderManager().destroyLoader(DATABASE_LOADER_ID);
} else {
restartLoaders();
}
return true;
}
@Override
public boolean onQueryTextSubmit(String query) {
return false;
return true;
}
@Override
@@ -125,7 +128,7 @@ public class SearchFragment extends InstrumentedFragment implements
switch (id) {
case DATABASE_LOADER_ID:
mSearchLoader = new DatabaseResultLoader(activity, mQuery);
mSearchLoader = mSearchFeatureProvider.getDatabaseSearchLoader(activity, mQuery);
return mSearchLoader;
default:
return null;
@@ -142,17 +145,22 @@ public class SearchFragment extends InstrumentedFragment implements
}
@Override
public void onLoaderReset(Loader<List<SearchResult>> loader) { }
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.DASHBOARD_SEARCH_RESULTS;
public void onLoaderReset(Loader<List<SearchResult>> loader) {
}
private void clearLoaders() {
if (mSearchLoader != null) {
mSearchLoader.cancelLoad();
mSearchLoader = null;
}
private void restartLoaders() {
final LoaderManager loaderManager = getLoaderManager();
loaderManager.restartLoader(DATABASE_LOADER_ID, null /* args */, this /* callback */);
}
private SearchView makeSearchView(ActionBar actionBar, String query) {
final SearchView searchView = new SearchView(actionBar.getThemedContext());
searchView.setIconifiedByDefault(false);
searchView.setQuery(query, false /* submitQuery */);
searchView.setOnQueryTextListener(this);
final LayoutParams lp =
new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
searchView.setLayoutParams(lp);
return searchView;
}
}