How I can fix SearchView in my app, I have already add SearchView in my app, but it doesn't work.
Book Activity :
public class BookActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<Book>> {
public static final String LOG_TAG = BookActivity.class.getName();
/**
* Constant value for the earthquake loader ID. We can choose any integer.
* This really only comes into play if you're using multiple loader.
*/
private static final int BOOK_LOADER_ID = 1;
/**
* URL for books data from the Google Books API
*/
public static final String GOOGLE_REQUEST_URL = "https://www.googleapis.com/books/v1/volumes?q=war";
private BookAdapter mAdapter;
private TextView mEmptyStateTextView;
ListView bookListView;
SearchView bookSearchView;
ArrayList<Book> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.book_activity);
// Find a reference to the {@link ListView} in the layout
bookListView = (ListView) findViewById(R.id.list);
// Create a new adapter that takes the list of books as input
mAdapter = new BookAdapter(this, new ArrayList<>());
// Set the adapter on the {@link ListView}
// so the list can be populated in the user interface
bookListView.setAdapter(mAdapter);
ImageView mEmptyStateImageView = findViewById(R.id.empty_view_image);
bookListView.setEmptyView(mEmptyStateImageView);
mEmptyStateTextView = findViewById(R.id.empty_view);
bookListView.setEmptyView(mEmptyStateTextView);
// Set an item click listener on the ListView, which sends an intent to a web browser
// to open a website with more information about the selected book.
bookListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
// Find the current book that was clicked on
Book currentBook = mAdapter.getItem(position);
// Convert the String URL into a URI object (to pass into the Intent constructor)
assert currentBook != null;
Uri buyBookUri = Uri.parse(currentBook.getUrlBook());
// Create a new intent to view buy the book URI
Intent websiteIntent = new Intent(Intent.ACTION_VIEW, buyBookUri);
// Send the intent to launch a new activity
startActivity(websiteIntent);
}
});
bookSearchView = (SearchView) findViewById(R.id.search_view);
bookSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
Log.i(LOG_TAG, "Problem with onQueryTextSubmit in SearchView");
Toast.makeText(BookActivity.this,"No Book Found", Toast.LENGTH_LONG).show();
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
Log.i(LOG_TAG, "Problem with onQueryTextChange in SearchView");
mAdapter.getFilter().filter(newText);
return false;
}
});
// Get a reference to the ConnectivityManager to check state of network connectivity
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
// Get details on the currently active default data network
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
// If there is a network connection, fetch data
if (networkInfo != null && networkInfo.isConnected()) {
// Get a reference to the LoaderManager, in order to interact with loaders.
LoaderManager loaderManager = LoaderManager.getInstance(this);
// Initialize the loader. Pass in the int ID constant defined above and pass in null for
// the bundle. Pass in this activity for the LoaderCallbacks parameter (which is valid
// because this activity implements the LoaderCallbacks interface).
loaderManager.initLoader(BOOK_LOADER_ID, null, this);
} else {
// Otherwise, display error
// First, hide loading indicator so error message will be visible
View loadingIndicator = findViewById(R.id.loading_indicator);
loadingIndicator.setVisibility(View.GONE);
// Update empty state with no connection error message
mEmptyStateImageView.setImageResource(R.drawable.wifi_off);
mEmptyStateTextView.setText(R.string.no_internet_connection);
}
}
@Override
public Loader<List<Book>> onCreateLoader(int i, Bundle args) {
Log.i(LOG_TAG, "Problem with onCreateLoader");
return new BookLoader(this, GOOGLE_REQUEST_URL);
}
@Override
public void onLoadFinished(Loader<List<Book>> loader, List<Book> books) {
Log.i(LOG_TAG, "Problem in onLoadFinished");
View loadingIndicator = findViewById(R.id.loading_indicator);
loadingIndicator.setVisibility(View.GONE);
mEmptyStateTextView.setText(R.string.no_books);
mAdapter.clear();
if (books != null && !books.isEmpty()) {
mAdapter.addAll(books);
}
}
@Override
public void onLoaderReset(Loader<List<Book>> loader) {
Log.i(LOG_TAG, "Problem in onLoaderReset");
mAdapter.clear();
}
}
Book Adapter :
public class BookAdapter extends ArrayAdapter<Book> {
public BookAdapter (Activity context, ArrayList<Book> books) {
// Here, we initialize the ArrayAdapter's internal storage for the context and the list.
// the second argument is used when the ArrayAdapter is populating a single TextView.
// Because this is a custom adapter for two TextViews and an ImageView, the adapter is not
// going to use this second argument, so it can be any value. Here, we used 0.
super(context, 0, books);
}
/**
*
* @param position The position in the list of data that should be displayed in the
* list item view.
* @param convertView The recycled view to populate.
* @param parent The parent ViewGroup that is used for inflation.
* @return The View for the position in the AdapterView.
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Check if there is an existing list item view (Called convertView) that we can reuse,
// otherwise, if convertView is null, then inflate a new list item layout.
View listItemView = convertView;
if (listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(
R.layout.book_list_item, parent, false);
}
// Find the book at the given position in the list of books
final Book currentBook = getItem(position);
// Find the TextView with view ID bookName
TextView bookNameView = listItemView.findViewById(R.id.title);
// Display the bookName of the current book in that TextView
bookNameView.setText(currentBook.getTitle());
// Find the TextView with view ID bookAuthor
TextView bookAuthorView = listItemView.findViewById(R.id.author);
// Display the bookAuthor of the current book in that TextView
bookAuthorView.setText(currentBook.getAuthor());
// Find the TextView with view ID numberPage
TextView numberPageOfBookView = listItemView.findViewById(R.id.pageCount);
// Display the numberPage of the current book in that TextView
numberPageOfBookView.setText(currentBook.getPageCount());
// Find the TextView with view ID bookLanguage
TextView bookLanguageView = listItemView.findViewById(R.id.language);
// Display the bookLanguage of the current book in that TextView
bookLanguageView.setText(currentBook.getLanguage());
// Find the ImageView with view ID bookCover
ImageView bookImageCover = listItemView.findViewById(R.id.cover_image);
// Display the book cover of the current book in that book
Picasso.get().load(currentBook.getImageUrl()).into(bookImageCover);
return listItemView;
}
}
Book Utils :
public final class BookUtils {
private static final String LOG_TAG = BookUtils.class.getSimpleName();
/**
* Create a private constructor because no one should ever create a {@link BookUtils} object.
* This class is only meant to hold static variables and methods, which can be accessed
* directly from the class name QueryUtils (and an object instance of QueryUtils is not needed).
*/
private BookUtils() {
}
/** Sample JSON response for a USGS query */
public static List<Book> fetchBookData(String requestUrl) {
// Create URL object
URL url = createUrl(requestUrl);
// Perform HTTP request to the URL and receive a JSON response back
String jsonResponse = null;
try {
jsonResponse = makeHttpRequest(url);
} catch (IOException e) {
Log.e(LOG_TAG, "Problem making the HTTP request.", e);
}
// Extract relevant fields from the JSON response and create a list of {@link Earthquake}s
List<Book> books = extractBookFromJson(jsonResponse);
// Return the list of {@link Earthquake}s
return books;
}
/**
* Returns new URL object from the given string URL.
*/
private static URL createUrl(String stringUrl) {
URL url = null;
try {
url = new URL(stringUrl);
} catch (MalformedURLException e) {
Log.e(LOG_TAG, "Problem building the URL ", e);
}
return url;
}
private static String makeHttpRequest(URL url) throws IOException {
String jsonResponse = "";
// If the URL is null, then return early.
if (url == null) {
return jsonResponse;
}
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setReadTimeout(10000 /* milliseconds */);
urlConnection.setConnectTimeout(15000 /* milliseconds */);
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// If the request was successful (response code 200),
// then read the input stream and parse the response.
if (urlConnection.getResponseCode() == 200) {
inputStream = urlConnection.getInputStream();
jsonResponse = readFromStream(inputStream);
} else {
Log.e(LOG_TAG, "Error response code: " + urlConnection.getResponseCode());
}
} catch (IOException e) {
Log.e(LOG_TAG, "Problem retrieving the book JSON results.", e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (inputStream != null) {
// Closing the input stream could throw an IOException, which is why
// the makeHttpRequest(URL url) method signature specifies than an IOException
// could be thrown.
inputStream.close();
}
}
return jsonResponse;
}
/**
* Convert the {@link InputStream} into a String which contains the
* whole JSON response from the server.
*/
private static String readFromStream(InputStream inputStream) throws IOException {
StringBuilder output = new StringBuilder();
if (inputStream != null) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(inputStreamReader);
String line = reader.readLine();
while (line != null) {
output.append(line);
line = reader.readLine();
}
}
return output.toString();
}
/**
* Return a list of {@link Book} objects that has been built up from
* parsing a JSON response.
*/
public static List<Book> extractBookFromJson(String bookJSON) {
if (TextUtils.isEmpty(bookJSON)){
return null;
}
// Create an empty ArrayList that we can start adding earthquakes to
List<Book> books = new ArrayList<>();
// Try to parse the SAMPLE_JSON_RESPONSE. If there's a problem with the way the JSON
// is formatted, a JSONException exception object will be thrown.
// Catch the exception so the app doesn't crash, and print the error message to the logs.
try {
JSONObject baseJsonResponse = new JSONObject(bookJSON);
JSONArray bookArray = baseJsonResponse.getJSONArray("items");
for( int i = 0; i < bookArray.length(); i++) {
JSONObject currentBook = bookArray.getJSONObject(i);
JSONObject volumeInfo = currentBook.getJSONObject("volumeInfo");
String author;
if (volumeInfo.has("authors")) {
JSONArray authors = volumeInfo.getJSONArray("authors");
Log.println(Log.INFO, LOG_TAG, String.valueOf(authors));
if (!volumeInfo.isNull("authors")) {
author = (String) authors.get(0);
} else {
author = "*** unknown author ***";
}
} else {
author = "*** missing info of authors ***";
}
JSONObject imageLinks = volumeInfo.getJSONObject("imageLinks");
Log.println(Log.INFO, LOG_TAG, String.valueOf(imageLinks));
String title = volumeInfo.getString("title");
String pageCount = volumeInfo.getString("pageCount");
String language = volumeInfo.getString("language");
String bookUrl = volumeInfo.getString("previewLink");
String coverImageUrl = imageLinks.getString("smallThumbnail");
StringBuilder stringBuilder = new StringBuilder();
Pattern p = Pattern.compile("id=(.*?)&");
Matcher m = p.matcher(coverImageUrl);
if (m.matches()) {
String id = m.group(1);
coverImageUrl = String.valueOf(stringBuilder.append("https://books.google.com/books/content/images/frontcover/").append(id).append("?fife=w300"));
} else {
Log.i(LOG_TAG, "Issues with cover");
}
Book book = new Book(title, author, pageCount, language, bookUrl, coverImageUrl);
books.add(book);
}
} catch (JSONException e) {
// If an error is thrown when executing any of the above statements in the "try" block,
// catch the exception here, so the app doesn't crash. Print a log message
// with the message from the exception.
Log.e("BookUtils", "Problem parsing the book JSON results", e);
}
// Return the list of earthquakes
return books;
}
}