Merge "Clean up search fragment loader lifecycle."

This commit is contained in:
Fan Zhang
2016-12-07 00:58:42 +00:00
committed by Android (Google) Code Review
9 changed files with 210 additions and 98 deletions

View File

@@ -28,9 +28,9 @@ import android.view.View;
import android.view.ViewGroup;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.overlay.SupportFeatureProvider;
@@ -77,7 +77,7 @@ public final class DashboardContainerFragment extends InstrumentedFragment {
// check if support tab needs to be selected
final String selectedTab = getArguments().
getString(EXTRA_SELECT_SETTINGS_TAB, ARG_SUMMARY_TAB);
getString(EXTRA_SELECT_SETTINGS_TAB, ARG_SUMMARY_TAB);
if (TextUtils.equals(selectedTab, ARG_SUPPORT_TAB)) {
mViewPager.setCurrentItem(INDEX_SUPPORT_FRAGMENT);
} else {

View File

@@ -22,7 +22,6 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.SimpleItemAnimator;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;

View File

@@ -16,7 +16,7 @@
package com.android.settings.search2;
import android.app.Activity;
import android.widget.SearchView;
import android.content.Context;
import android.view.Menu;
/**
@@ -31,8 +31,14 @@ public interface SearchFeatureProvider {
/**
* Inserts the Menu items into Settings activity.
*
* @param menu Items will be inserted into this menu.
* @param activity The activity that precedes SearchActivity.
*/
void setUpSearchMenu(Menu menu, Activity activity);
/**
* Returns a new loader to search in index database.
*/
DatabaseResultLoader getDatabaseSearchLoader(Context context, String query);
}

View File

@@ -24,6 +24,9 @@ import android.view.Menu;
import android.view.MenuItem;
import com.android.settings.R;
import com.android.settings.utils.AsyncLoader;
import java.util.List;
/**
* FeatureProvider for the refactored search code.
@@ -60,4 +63,9 @@ public class SearchFeatureProviderImpl implements SearchFeatureProvider {
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
@Override
public DatabaseResultLoader getDatabaseSearchLoader(Context context, String query) {
return new DatabaseResultLoader(context, query);
}
}

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;
}
}

View File

@@ -28,10 +28,11 @@ import com.android.settings.search2.ResultPayload.PayloadType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SearchResultsAdapter extends Adapter<SearchViewHolder> {
private ArrayList<SearchResult> mSearchResults;
private HashMap<String, List<SearchResult>> mResultsMap;
private final List<SearchResult> mSearchResults;
private final Map<String, List<SearchResult>> mResultsMap;
public SearchResultsAdapter() {
mSearchResults = new ArrayList<>();
@@ -45,13 +46,19 @@ public class SearchResultsAdapter extends Adapter<SearchViewHolder> {
return;
}
mResultsMap.put(loaderClassName, freshResults);
mSearchResults = mergeMappedResults();
mSearchResults.addAll(mergeMappedResults());
notifyDataSetChanged();
}
public void clearResults() {
mSearchResults.clear();
mResultsMap.clear();
notifyDataSetChanged();
}
private ArrayList<SearchResult> mergeMappedResults() {
ArrayList<SearchResult> mergedResults = new ArrayList<>();
for(String key : mResultsMap.keySet()) {
for (String key : mResultsMap.keySet()) {
mergedResults.addAll(mResultsMap.get(key));
}
return mergedResults;
@@ -60,7 +67,7 @@ public class SearchResultsAdapter extends Adapter<SearchViewHolder> {
@Override
public SearchViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch(viewType) {
switch (viewType) {
case PayloadType.INTENT:
View view = inflater.inflate(R.layout.search_intent_item, parent, false);
return new IntentSearchViewHolder(view);
@@ -95,7 +102,7 @@ public class SearchResultsAdapter extends Adapter<SearchViewHolder> {
}
@VisibleForTesting
public ArrayList<SearchResult> getSearchResults() {
public List<SearchResult> getSearchResults() {
return mSearchResults;
}
}