Search code examples
androidjsongoogle-books

while parsing JSON book data "no book found" logic doesn't work in android


I am using GOOGLE_BOOK_API to parse JSON data. when user enter keyword in search view which is not in list then mEmptyStateTextView doesn't work which says no book found. below is my code.

BookActivity.java //book details

public class BookActivity extends AppCompatActivity {

/**
 * URL for book data from the google book dataset
 */
private static final String GOOGLE_REQUEST_SEARCH_URL = "https://www.googleapis.com/books/v1/volumes?maxResults=20&q=";
View loadingIndicator;
ArrayList<Book> books;
ConnectivityManager connectivityManager;
NetworkInfo networkInfo;
/**
 * Adapter for the list of earthquakes
 */
private BookAdapter mAdapter;
private TextView mEmptyStateTextView;

@Override
protected void onSaveInstanceState(Bundle keepState) {
    keepState.putParcelableArrayList("booklist", books);
    Log.v("My Log message", "book is :" + books);
    super.onSaveInstanceState(keepState);
}


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_book);
    loadingIndicator = findViewById(R.id.loading_indicator);
    loadingIndicator.setVisibility(View.GONE);

    // Find a reference to the {@link ListView} in the layout
    ListView bookListView = (ListView) findViewById(R.id.list);

    mEmptyStateTextView = (TextView) findViewById(R.id.empty_view);
    mEmptyStateTextView.setText(R.string.no_data);
    bookListView.setEmptyView(mEmptyStateTextView);

    // Create a new adapter that takes an empty list of books as input
    mAdapter = new BookAdapter(this, new ArrayList<Book>());

    // Set the adapter on the {@link ListView}
    // so the list can be populated in the user interface
    bookListView.setAdapter(mAdapter);

    if (savedInstanceState != null) {
        books = savedInstanceState.getParcelableArrayList("booklist");
        mAdapter.addAll(books);

    } else {
        books = new ArrayList<>();

    }
    bookListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
            Book currentBook = mAdapter.getItem(position);

            Uri bookUri = Uri.parse(currentBook.getUrl());

            Intent websiteIntent = new Intent(Intent.ACTION_VIEW, bookUri);

            startActivity(websiteIntent);
        }
    });


   /* if (networkInfo != null && networkInfo.isConnected()) {

        BookAsyncTask task = new BookAsyncTask();
        task.execute(GOOGLE_REQUEST_SEARCH_URL);
    } else {

        loadingIndicator = findViewById(R.id.loading_indicator);
        loadingIndicator.setVisibility(View.GONE);

        mEmptyStateTextView.setText(R.string.no_internet_connection);
    }*/
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.options_menu, menu);

    SearchManager searchManager =
            (SearchManager) getSystemService(Context.SEARCH_SERVICE);

    MenuItem searchItem = menu.findItem(R.id.search);
    final SearchView searchView = (SearchView) searchItem.getActionView();

    searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {

            String urlQuery;
            query = searchView.getQuery().toString();

            connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

            networkInfo = connectivityManager.getActiveNetworkInfo();
            if (networkInfo != null && networkInfo.isConnected()) {

                BookAsyncTask task = new BookAsyncTask();
                task.execute(GOOGLE_REQUEST_SEARCH_URL);

                if (!TextUtils.isEmpty(query)) {

                    String encodedQuery = "";
                    try {
                        encodedQuery = URLEncoder.encode(query, "utf-8");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    urlQuery = GOOGLE_REQUEST_SEARCH_URL + encodedQuery + "&maxResults=10";

                    //Toast.makeText(getApplicationContext(), urlQuery, Toast.LENGTH_SHORT).show();
                    mAdapter.clear();
                    mEmptyStateTextView.setText(""); // clear any message set previously
                    loadingIndicator.setVisibility(View.VISIBLE); // show loading during search
                    new BookAsyncTask().execute(urlQuery);
                }

            } else {

                Toast.makeText(getApplicationContext(), "Network not available", Toast.LENGTH_SHORT).show();
            }
            return true;
        }

        @Override
        public boolean onQueryTextChange(String newText) {

            return false;
        }
    });

    return true;
}

private class BookAsyncTask extends AsyncTask<String, Void, ArrayList<Book>> {
    @Override
    protected ArrayList<Book> doInBackground(String... urls) {

        if (urls.length < 1 || urls[0] == null) {
            return null;
        }

        ArrayList<Book> result = QueryUtils.fetchBook(urls[0]);
        return result;
    }

    @Override
    protected void onPostExecute(ArrayList<Book> result) {

        loadingIndicator = findViewById(R.id.loading_indicator);
        loadingIndicator.setVisibility(View.GONE);

        mAdapter.clear();

        if (result == null) {
            return;
        }
        if (result != null && !result.isEmpty()) {
            books = result;
            mAdapter.addAll(result);
        }

        mEmptyStateTextView.setText(R.string.no_book_found);

    }
}

}

activity_book.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<!-- Layout for a list of books -->
<ListView
    android:id="@+id/list"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:dividerHeight="0dp"
    android:divider="@null"/>

<!-- Empty view is only visible when the list has no items. -->
<TextView
    android:id="@+id/empty_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:paddingLeft="@dimen/padding_left"
    android:paddingRight="@dimen/padding_right"
    android:textAppearance="?android:textAppearanceMedium"/>

<!-- Loading indicator is only shown before the first load -->
<ProgressBar
    android:id="@+id/loading_indicator"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"/>

</RelativeLayout>

Solution

  • You are calling BookAsyncTask two times in fetch url method, the first one is hitting api https://www.googleapis.com/books/v1/volumes?maxResults=20&q=‌​(that is wrong params) and the second one is hitting with the correct params.

    And according to android guidelines(more details)regarding Asynctask, only one instance of Asynctask can be executed at a time, so the second correct URL never gets call and you got the response hit first hit which is no book found

    Replace your onQueryTextSubmit complete method with the method given below,

    public boolean onQueryTextSubmit(String query) {
    
            String urlQuery;
            query = searchView.getQuery().toString();
    
            connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    
            networkInfo = connectivityManager.getActiveNetworkInfo();
            if (networkInfo != null && networkInfo.isConnected()) {
    
                //BookAsyncTask task = new BookAsyncTask(); //Removing this and below will solve the problem
                //task.execute(GOOGLE_REQUEST_SEARCH_URL);//Removing this will solve the problem
    
                if (!TextUtils.isEmpty(query)) {
    
                    String encodedQuery = "";
                    try {
                        encodedQuery = URLEncoder.encode(query, "utf-8");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    urlQuery = GOOGLE_REQUEST_SEARCH_URL + encodedQuery + "&maxResults=10";
    
                    //Toast.makeText(getApplicationContext(), urlQuery, Toast.LENGTH_SHORT).show();
                    mAdapter.clear();
                    mEmptyStateTextView.setText(""); // clear any message set previously
                    loadingIndicator.setVisibility(View.VISIBLE); // show loading during search
                    new BookAsyncTask().execute(urlQuery);
                }
    
            } else {
    
                Toast.makeText(getApplicationContext(), "Network not available", Toast.LENGTH_SHORT).show();
            }
            return true;
        }
    

    EDIT: Check out a very good tutorial on this link which fetch and parse the JSON data into JAVA model using GSON framework