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:
@@ -1,23 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2016 The Android Open Source Project
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
-->
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item
|
|
||||||
android:id="@+id/search"
|
|
||||||
android:title="@string/search_menu"
|
|
||||||
android:icon="@*android:drawable/ic_search_api_material"
|
|
||||||
android:showAsAction="collapseActionView|ifRoom"
|
|
||||||
android:actionViewClass="android.widget.SearchView"/>
|
|
||||||
</menu>
|
|
@@ -28,9 +28,9 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import com.android.internal.logging.nano.MetricsProto;
|
import com.android.internal.logging.nano.MetricsProto;
|
||||||
import com.android.settings.core.InstrumentedFragment;
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.SettingsActivity;
|
import com.android.settings.SettingsActivity;
|
||||||
|
import com.android.settings.core.InstrumentedFragment;
|
||||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||||
import com.android.settings.overlay.FeatureFactory;
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
import com.android.settings.overlay.SupportFeatureProvider;
|
import com.android.settings.overlay.SupportFeatureProvider;
|
||||||
|
@@ -22,7 +22,6 @@ import android.os.AsyncTask;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
import android.support.v7.widget.SimpleItemAnimator;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
package com.android.settings.search2;
|
package com.android.settings.search2;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.widget.SearchView;
|
import android.content.Context;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -31,8 +31,14 @@ public interface SearchFeatureProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts the Menu items into Settings activity.
|
* Inserts the Menu items into Settings activity.
|
||||||
|
*
|
||||||
* @param menu Items will be inserted into this menu.
|
* @param menu Items will be inserted into this menu.
|
||||||
* @param activity The activity that precedes SearchActivity.
|
* @param activity The activity that precedes SearchActivity.
|
||||||
*/
|
*/
|
||||||
void setUpSearchMenu(Menu menu, Activity activity);
|
void setUpSearchMenu(Menu menu, Activity activity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new loader to search in index database.
|
||||||
|
*/
|
||||||
|
DatabaseResultLoader getDatabaseSearchLoader(Context context, String query);
|
||||||
}
|
}
|
||||||
|
@@ -24,6 +24,9 @@ import android.view.Menu;
|
|||||||
|
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.utils.AsyncLoader;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FeatureProvider for the refactored search code.
|
* FeatureProvider for the refactored search code.
|
||||||
@@ -60,4 +63,9 @@ public class SearchFeatureProviderImpl implements SearchFeatureProvider {
|
|||||||
|
|
||||||
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DatabaseResultLoader getDatabaseSearchLoader(Context context, String query) {
|
||||||
|
return new DatabaseResultLoader(context, query);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,51 +16,72 @@
|
|||||||
|
|
||||||
package com.android.settings.search2;
|
package com.android.settings.search2;
|
||||||
|
|
||||||
|
import android.app.ActionBar;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.LoaderManager;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Loader;
|
import android.content.Loader;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.app.LoaderManager;
|
import android.support.annotation.VisibleForTesting;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.Menu;
|
import android.widget.LinearLayout.LayoutParams;
|
||||||
import android.view.MenuInflater;
|
|
||||||
import android.widget.SearchView;
|
import android.widget.SearchView;
|
||||||
|
|
||||||
import com.android.internal.logging.nano.MetricsProto;
|
import com.android.internal.logging.nano.MetricsProto;
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.core.InstrumentedFragment;
|
import com.android.settings.core.InstrumentedFragment;
|
||||||
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SearchFragment extends InstrumentedFragment implements
|
public class SearchFragment extends InstrumentedFragment implements
|
||||||
SearchView.OnQueryTextListener, MenuItem.OnActionExpandListener,
|
SearchView.OnQueryTextListener, LoaderManager.LoaderCallbacks<List<SearchResult>> {
|
||||||
LoaderManager.LoaderCallbacks<List<SearchResult>> {
|
|
||||||
|
|
||||||
|
// State values
|
||||||
|
static final String STATE_QUERY = "query";
|
||||||
|
|
||||||
|
// Loader IDs
|
||||||
private static final int DATABASE_LOADER_ID = 0;
|
private static final int DATABASE_LOADER_ID = 0;
|
||||||
|
|
||||||
private SearchResultsAdapter mSearchAdapter;
|
@VisibleForTesting
|
||||||
|
String mQuery;
|
||||||
|
|
||||||
|
private SearchFeatureProvider mSearchFeatureProvider;
|
||||||
private DatabaseResultLoader mSearchLoader;
|
private DatabaseResultLoader mSearchLoader;
|
||||||
|
|
||||||
|
private SearchResultsAdapter mSearchAdapter;
|
||||||
private RecyclerView mResultsRecyclerView;
|
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
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
|
|
||||||
mSearchAdapter = new SearchResultsAdapter();
|
mSearchAdapter = new SearchResultsAdapter();
|
||||||
|
if (savedInstanceState != null) {
|
||||||
final LoaderManager loaderManager = getLoaderManager();
|
mQuery = savedInstanceState.getString(STATE_QUERY);
|
||||||
loaderManager.initLoader(DATABASE_LOADER_ID, null, this);
|
getLoaderManager().initLoader(DATABASE_LOADER_ID, null, this);
|
||||||
|
}
|
||||||
|
final ActionBar actionBar = getActivity().getActionBar();
|
||||||
|
actionBar.setCustomView(makeSearchView(actionBar, mQuery));
|
||||||
|
actionBar.setDisplayShowCustomEnabled(true);
|
||||||
|
actionBar.setDisplayShowTitleEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -68,55 +89,37 @@ public class SearchFragment extends InstrumentedFragment implements
|
|||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
final View view = inflater.inflate(R.layout.search_panel_2, container, false);
|
final View view = inflater.inflate(R.layout.search_panel_2, container, false);
|
||||||
mResultsRecyclerView = (RecyclerView) view.findViewById(R.id.list_results);
|
mResultsRecyclerView = (RecyclerView) view.findViewById(R.id.list_results);
|
||||||
|
|
||||||
mResultsRecyclerView.setAdapter(mSearchAdapter);
|
mResultsRecyclerView.setAdapter(mSearchAdapter);
|
||||||
mResultsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
|
mResultsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
super.onCreateOptionsMenu(menu, inflater);
|
super.onSaveInstanceState(outState);
|
||||||
inflater.inflate(R.menu.search_options_menu, menu);
|
outState.putString(STATE_QUERY, mQuery);
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onQueryTextChange(String query) {
|
public boolean onQueryTextChange(String query) {
|
||||||
if (query == null || query.equals(mQuery)) {
|
if (TextUtils.equals(query, mQuery)) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
mQuery = query;
|
mQuery = query;
|
||||||
clearLoaders();
|
mSearchAdapter.clearResults();
|
||||||
|
|
||||||
final LoaderManager loaderManager = getLoaderManager();
|
if (TextUtils.isEmpty(mQuery)) {
|
||||||
loaderManager.restartLoader(DATABASE_LOADER_ID, null, this);
|
getLoaderManager().destroyLoader(DATABASE_LOADER_ID);
|
||||||
|
} else {
|
||||||
|
restartLoaders();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onQueryTextSubmit(String query) {
|
public boolean onQueryTextSubmit(String query) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -125,7 +128,7 @@ public class SearchFragment extends InstrumentedFragment implements
|
|||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case DATABASE_LOADER_ID:
|
case DATABASE_LOADER_ID:
|
||||||
mSearchLoader = new DatabaseResultLoader(activity, mQuery);
|
mSearchLoader = mSearchFeatureProvider.getDatabaseSearchLoader(activity, mQuery);
|
||||||
return mSearchLoader;
|
return mSearchLoader;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
@@ -142,17 +145,22 @@ public class SearchFragment extends InstrumentedFragment implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoaderReset(Loader<List<SearchResult>> loader) { }
|
public void onLoaderReset(Loader<List<SearchResult>> loader) {
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMetricsCategory() {
|
|
||||||
return MetricsProto.MetricsEvent.DASHBOARD_SEARCH_RESULTS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearLoaders() {
|
private void restartLoaders() {
|
||||||
if (mSearchLoader != null) {
|
final LoaderManager loaderManager = getLoaderManager();
|
||||||
mSearchLoader.cancelLoad();
|
loaderManager.restartLoader(DATABASE_LOADER_ID, null /* args */, this /* callback */);
|
||||||
mSearchLoader = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,10 +28,11 @@ import com.android.settings.search2.ResultPayload.PayloadType;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class SearchResultsAdapter extends Adapter<SearchViewHolder> {
|
public class SearchResultsAdapter extends Adapter<SearchViewHolder> {
|
||||||
private ArrayList<SearchResult> mSearchResults;
|
private final List<SearchResult> mSearchResults;
|
||||||
private HashMap<String, List<SearchResult>> mResultsMap;
|
private final Map<String, List<SearchResult>> mResultsMap;
|
||||||
|
|
||||||
public SearchResultsAdapter() {
|
public SearchResultsAdapter() {
|
||||||
mSearchResults = new ArrayList<>();
|
mSearchResults = new ArrayList<>();
|
||||||
@@ -45,13 +46,19 @@ public class SearchResultsAdapter extends Adapter<SearchViewHolder> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mResultsMap.put(loaderClassName, freshResults);
|
mResultsMap.put(loaderClassName, freshResults);
|
||||||
mSearchResults = mergeMappedResults();
|
mSearchResults.addAll(mergeMappedResults());
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearResults() {
|
||||||
|
mSearchResults.clear();
|
||||||
|
mResultsMap.clear();
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<SearchResult> mergeMappedResults() {
|
private ArrayList<SearchResult> mergeMappedResults() {
|
||||||
ArrayList<SearchResult> mergedResults = new ArrayList<>();
|
ArrayList<SearchResult> mergedResults = new ArrayList<>();
|
||||||
for(String key : mResultsMap.keySet()) {
|
for (String key : mResultsMap.keySet()) {
|
||||||
mergedResults.addAll(mResultsMap.get(key));
|
mergedResults.addAll(mResultsMap.get(key));
|
||||||
}
|
}
|
||||||
return mergedResults;
|
return mergedResults;
|
||||||
@@ -60,7 +67,7 @@ public class SearchResultsAdapter extends Adapter<SearchViewHolder> {
|
|||||||
@Override
|
@Override
|
||||||
public SearchViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
public SearchViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
||||||
switch(viewType) {
|
switch (viewType) {
|
||||||
case PayloadType.INTENT:
|
case PayloadType.INTENT:
|
||||||
View view = inflater.inflate(R.layout.search_intent_item, parent, false);
|
View view = inflater.inflate(R.layout.search_intent_item, parent, false);
|
||||||
return new IntentSearchViewHolder(view);
|
return new IntentSearchViewHolder(view);
|
||||||
@@ -95,7 +102,7 @@ public class SearchResultsAdapter extends Adapter<SearchViewHolder> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public ArrayList<SearchResult> getSearchResults() {
|
public List<SearchResult> getSearchResults() {
|
||||||
return mSearchResults;
|
return mSearchResults;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,20 +20,25 @@ package com.android.settings.search;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
import com.android.settings.SettingsRobolectricTestRunner;
|
import com.android.settings.SettingsRobolectricTestRunner;
|
||||||
import com.android.settings.TestConfig;
|
import com.android.settings.TestConfig;
|
||||||
import com.android.settings.search2.*;
|
import com.android.settings.search2.DatabaseResultLoader;
|
||||||
|
import com.android.settings.search2.IntentPayload;
|
||||||
|
import com.android.settings.search2.ResultPayload;
|
||||||
|
import com.android.settings.search2.SearchResult;
|
||||||
import com.android.settings.search2.SearchResult.Builder;
|
import com.android.settings.search2.SearchResult.Builder;
|
||||||
import com.android.settings.R;
|
import com.android.settings.search2.SearchResultsAdapter;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import org.robolectric.annotation.Config;
|
|
||||||
import org.robolectric.Robolectric;
|
import org.robolectric.Robolectric;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
@@ -78,7 +83,7 @@ public class SearchAdapterTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNoResultsAdded_EmptyListReturned() {
|
public void testNoResultsAdded_EmptyListReturned() {
|
||||||
ArrayList<SearchResult> updatedResults = mAdapter.getSearchResults();
|
List<SearchResult> updatedResults = mAdapter.getSearchResults();
|
||||||
assertThat(updatedResults).isEmpty();
|
assertThat(updatedResults).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +93,7 @@ public class SearchAdapterTest {
|
|||||||
ArrayList<SearchResult> intentResults = getIntentSampleResults();
|
ArrayList<SearchResult> intentResults = getIntentSampleResults();
|
||||||
mAdapter.mergeResults(intentResults, mLoaderClassName);
|
mAdapter.mergeResults(intentResults, mLoaderClassName);
|
||||||
|
|
||||||
ArrayList<SearchResult> updatedResults = mAdapter.getSearchResults();
|
List<SearchResult> updatedResults = mAdapter.getSearchResults();
|
||||||
assertThat(updatedResults).containsAllIn(intentResults);
|
assertThat(updatedResults).containsAllIn(intentResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +103,7 @@ public class SearchAdapterTest {
|
|||||||
mAdapter.mergeResults(intentResults, mLoaderClassName);
|
mAdapter.mergeResults(intentResults, mLoaderClassName);
|
||||||
mAdapter.mergeResults(intentResults, mLoaderClassName);
|
mAdapter.mergeResults(intentResults, mLoaderClassName);
|
||||||
|
|
||||||
ArrayList<SearchResult> updatedResults = mAdapter.getSearchResults();
|
List<SearchResult> updatedResults = mAdapter.getSearchResults();
|
||||||
assertThat(updatedResults).containsAllIn(intentResults);
|
assertThat(updatedResults).containsAllIn(intentResults);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.search2;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settings.testutils.FakeFeatureFactory;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Answers;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.robolectric.Robolectric;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
import org.robolectric.util.ActivityController;
|
||||||
|
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.anyString;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||||
|
public class SearchFragmentTest {
|
||||||
|
|
||||||
|
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||||
|
private Context mContext;
|
||||||
|
@Mock
|
||||||
|
private DatabaseResultLoader mDatabaseResultLoader;
|
||||||
|
private FakeFeatureFactory mFeatureFactory;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
FakeFeatureFactory.setupForTest(mContext);
|
||||||
|
mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void screenRotate_shouldPersistQuery() {
|
||||||
|
when(mFeatureFactory.searchFeatureProvider
|
||||||
|
.getDatabaseSearchLoader(any(Context.class), anyString()))
|
||||||
|
.thenReturn(mDatabaseResultLoader);
|
||||||
|
|
||||||
|
final Bundle bundle = new Bundle();
|
||||||
|
final String testQuery = "test";
|
||||||
|
ActivityController<SearchActivity> activityController =
|
||||||
|
Robolectric.buildActivity(SearchActivity.class);
|
||||||
|
activityController.setup();
|
||||||
|
SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager()
|
||||||
|
.findFragmentById(R.id.main_content);
|
||||||
|
|
||||||
|
fragment.mQuery = testQuery;
|
||||||
|
|
||||||
|
activityController.saveInstanceState(bundle).pause().stop().destroy();
|
||||||
|
|
||||||
|
activityController = Robolectric.buildActivity(SearchActivity.class);
|
||||||
|
activityController.setup(bundle);
|
||||||
|
|
||||||
|
verify(mFeatureFactory.searchFeatureProvider)
|
||||||
|
.getDatabaseSearchLoader(any(Context.class), anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryTextChange_shouldTriggerLoader() {
|
||||||
|
when(mFeatureFactory.searchFeatureProvider
|
||||||
|
.getDatabaseSearchLoader(any(Context.class), anyString()))
|
||||||
|
.thenReturn(mDatabaseResultLoader);
|
||||||
|
|
||||||
|
final String testQuery = "test";
|
||||||
|
ActivityController<SearchActivity> activityController =
|
||||||
|
Robolectric.buildActivity(SearchActivity.class);
|
||||||
|
activityController.setup();
|
||||||
|
SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager()
|
||||||
|
.findFragmentById(R.id.main_content);
|
||||||
|
|
||||||
|
fragment.onQueryTextChange(testQuery);
|
||||||
|
|
||||||
|
verify(mFeatureFactory.searchFeatureProvider)
|
||||||
|
.getDatabaseSearchLoader(any(Context.class), anyString());
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user