Я использовал Retrofit 2.0 (только что узнал, как его использовать), чтобы получить информацию об API Google Книг, и мне это удалось. Но теперь я не знаю, как передать его в RecyclerView, так как теперь мои модели были пересмотрены и теперь работают с вложенными моделями (я думаю, что это правильный термин) по сравнению с тем, что у меня было раньше ( старое переполнение стека)вопрос здесь ).
В настоящее время я получаю эту ошибку:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android_myneighborsbookshelf, PID: 8806
java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object java.util.List.get(int)' on a null object reference
at com.example.android_myneighborsbookshelf.adapters.SearchViewRecyclerViewAdapter.onBindViewHolder(SearchViewRecyclerViewAdapter.java:90)
at com.example.android_myneighborsbookshelf.adapters.SearchViewRecyclerViewAdapter.onBindViewHolder(SearchViewRecyclerViewAdapter.java:27)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7033)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7075)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5991)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6258)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6097)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6093)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4115)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3832)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4385)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1083)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1812)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1656)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1565)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at androidx.appcompat.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:446)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1812)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1656)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1565)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:753)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2792)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2319)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1460)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7183)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949)
at android.view.Choreographer.doCallbacks(Choreographer.java:761)
at android.view.Choreographer.doFrame(Choreographer.java:696)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Вот моя модель Book2.java
public class Book2 {
// @SerializedName("title")
private String mTitle;
@SerializedName("items")
private List<Items> items;
public Book2() {
// no arg constructor needed
}
public Book2(Items items) { // <-- not too sure if this is correct
this.mTitle = mTitle; // <-- not too sure if this is correct
}
public List<Items> getItems() {
return items;
}
public void setItems(List<Items> items) {
this.items = items;
}
public class Items {
@SerializedName("volumeInfo")
private VolumeInfo volumeInfo;
public VolumeInfo getVolumeInfo() {
return volumeInfo;
}
public void setVolumeInfo(VolumeInfo volumeInfo) {
this.volumeInfo = volumeInfo;
}
}
public static class VolumeInfo extends Book2 {
@SerializedName("title")
private String mTitle;
@SerializedName("authors")
private ArrayList<String> mAuthors;
@SerializedName("publisher")
private String mPublisher;
@SerializedName("publishedDate")
private String mPublishedDate;
@SerializedName("description")
private String mDescription;
// @SerializedName("industryIdentifiers")
// private ArrayList<String> mIndustryIdentifiers;
@SerializedName("categories")
private ArrayList<String> mCategories;
@SerializedName("imageLinks")
private ImageLinks mImageLinks;
public VolumeInfo(String title) {
this.mTitle = title;
}
public String getmTitle() {
return mTitle;
}
public void setmTitle(String mTitle) {
this.mTitle = mTitle;
}
public ArrayList<String> getmAuthors() {
return mAuthors;
}
public void setmAuthors(ArrayList<String> mAuthors) {
this.mAuthors = mAuthors;
}
public String getmPublisher() {
return mPublisher;
}
public void setmPublisher(String mPublisher) {
this.mPublisher = mPublisher;
}
public String getmPublishedDate() {
return mPublishedDate;
}
public void setmPublishedDate(String mPublishedDate) {
this.mPublishedDate = mPublishedDate;
}
public String getmDescription() {
return mDescription;
}
public void setmDescription(String mDescription) {
this.mDescription = mDescription;
}
/*
public ArrayList<String> getmIndustryIdentifiers() {
return mIndustryIdentifiers;
}
public void setmIndustryIdentifiers(ArrayList<String> mIndustryIdentifiers) {
this.mIndustryIdentifiers = mIndustryIdentifiers;
}
*/
public ArrayList<String> getmCategories() {
return mCategories;
}
public void setmCategories(ArrayList<String> mCategories) {
this.mCategories = mCategories;
}
public ImageLinks getmImageLinks() {
return mImageLinks;
}
public void setmImageLinks(ImageLinks mImageLinks) {
this.mImageLinks = mImageLinks;
}
}
public class ImageLinks {
@SerializedName("thumbnail")
private String mThumbnail;
public String getmThumbnail() {
return mThumbnail;
}
public void setmThumbnail(String mThumbnail) {
this.mThumbnail = mThumbnail;
}
}
}
MainActivity2.java
public class MainActivity2 extends AppCompatActivity {
private RecyclerView mRecyclerView;
private ArrayList<Book2> mBooks;
// private ArrayList<Book2> mBooks;
private SearchViewRecyclerViewAdapter mSearchViewRecyclerViewAdapter;
private RequestQueue mRequestQueue;
private static final String BASE_URL2="https://www.googleapis.com/books/v1/";
// private static final String BASE_URL_TYPICODE="https://jsonplaceholder.typicode.com/";
// private static final String BASE_URL="https://www.googleapis.com/books/v1/volumes?q=";
private EditText search_edit_text;
Button search_button;
ProgressBar loading_indicator;
private TextView error_message;
// private static final String LOG_TAG = MainActivity2.class.getSimpleName();
private static final String TAG = "MainActivity2";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_book_main2);
search_edit_text=findViewById(R.id.search_box);
search_button= findViewById(R.id.search_buttton);
loading_indicator=findViewById(R.id.loading_indicator);
error_message= findViewById(R.id.message_display);
mRecyclerView = findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mBooks = new ArrayList<>();
mRequestQueue = Volley.newRequestQueue(this);
search_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mBooks.clear();
search();
}
});
}
private void parseJson3(String key){
// source = https://medium.com/@wkrzywiec/making-use-of-open-rest-api-with-retrofit-dac6094f0522
// youtube tutorial here: https://www.youtube.com/watch?v=4JGvDUlfk7Y
JsonPlaceHolderApi serviceEndPoint = ServiceGenerator.createService(JsonPlaceHolderApi.class);
Call<Book2> call = serviceEndPoint.getQueryItems2("volumes?q=enders+game");
call.enqueue(new Callback<Book2>() {
@Override
public void onResponse(Call<Book2> call, retrofit2.Response<Book2> response) {
if (response.isSuccessful()) {
String title ="";
// List<String> author = "";
String author =" ";
String publishedDate = "Not Available";
String publisher = "Not Available";
String description = "No Description";
int pageCount = 1000;
String category = "No categories Available ";
String buy ="";
// String volumeInfoString = "";
String bookJSONString = null;
String thumbnail = "";
String previewLink = "";
String price = "";
String url = "";
// for (int i = 0; i < grantResults.length; i++) {
for (int i = 0; i < response.body().getItems().size(); i++) {
Log.d(TAG, "onResponse: success getmTitle: " + response.body().getItems().get(i).getVolumeInfo().getmTitle());
title = response.body().getItems().get(i).getVolumeInfo().getmTitle();
Log.d(TAG, "onResponse: success getmAuthors: " + response.body().getItems().get(i).getVolumeInfo().getmAuthors());
// author = response.body().getItems().get(i).getVolumeInfo().getmAuthors();
Log.d(TAG, "onResponse: success getmCategories: " + response.body().getItems().get(i).getVolumeInfo().getmCategories());
// category = response.body().getItems().get(i).getVolumeInfo().getmCategories();
Log.d(TAG, "onResponse: success getmDescription: " + response.body().getItems().get(i).getVolumeInfo().getmDescription());
description = response.body().getItems().get(i).getVolumeInfo().getmDescription();
Log.d(TAG, "onResponse: success getmPublisher: " + response.body().getItems().get(i).getVolumeInfo().getmPublisher());
publisher = response.body().getItems().get(i).getVolumeInfo().getmPublisher();
Log.d(TAG, "onResponse: success getmImageLinks: " + response.body().getItems().get(i).getVolumeInfo().getmImageLinks().getmThumbnail());
thumbnail = response.body().getItems().get(i).getVolumeInfo().getmImageLinks().getmThumbnail();
}
Log.d(TAG, "onResponse: title = " + title);
// mBooks.add(new Book2(title, author, publishedDate, description ,category
// , thumbnail, buy, previewLink, price, pageCount, url));
mBooks.add(new Book2.VolumeInfo(title));
mSearchViewRecyclerViewAdapter = new SearchViewRecyclerViewAdapter(MainActivity2.this , mBooks);
mRecyclerView.setAdapter(mSearchViewRecyclerViewAdapter);
} else {
Log.d(TAG, "onResponse: call in MainActivity2 was not successful");
}
}
@Override
public void onFailure(Call<Book2> call, Throwable t) {
Log.d(TAG, "onFailure: didnt work" + t);
}
});
}
private boolean Read_network_state(Context context)
{ boolean is_connected;
ConnectivityManager cm =(ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
is_connected=info!=null&&info.isConnectedOrConnecting();
return is_connected;
}
private void search()
{
String search_query = search_edit_text.getText().toString();
boolean is_connected = Read_network_state(this);
if(!is_connected)
{
error_message.setText(R.string.Failed_to_Load_data);
mRecyclerView.setVisibility(View.INVISIBLE);
error_message.setVisibility(View.VISIBLE);
return;
}
// Log.d("QUERY",search_query);
if(search_query.equals(""))
{
Toast.makeText(this,"Please enter your query",Toast.LENGTH_SHORT).show();
return;
}
String final_query=search_query.replace(" ","+");
Uri uri=Uri.parse(BASE_URL2+final_query);
// Uri uri=Uri.parse(BASE_URL+final_query);
Uri.Builder buider = uri.buildUpon();
parseJson3(buider.toString());
}
}
SearchViewRecyclerViewAdapter.java
public class SearchViewRecyclerViewAdapter extends RecyclerView.Adapter<SearchViewRecyclerViewAdapter.MyViewHolder> {
private Context mContext;
private List<Book2> mData;
private RequestOptions options;
private static final String LOG_TAG = SearchViewRecyclerViewAdapter.class.getSimpleName();
public SearchViewRecyclerViewAdapter(Context mContext, List<Book2> mData) {
this.mContext = mContext;
this.mData = mData;
//Request option for Glide
options = new RequestOptions().centerCrop().placeholder(R.drawable.loading_shape).error(R.drawable.loading_shape);
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {
View view;
LayoutInflater inflater = LayoutInflater.from(mContext);
view = inflater.inflate(R.layout.book_raw_item2 , parent , false);
final MyViewHolder viewHolder = new MyViewHolder(view);
viewHolder.container.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(mContext , BookProfileActivity2.class);
int pos = viewHolder.getAdapterPosition();
// i.putExtra("book_title" ,mData.get(pos).getTitle());
i.putExtra("book_title" ,mData.get(pos).getItems().get(pos).getVolumeInfo().getmTitle());
// i.putExtra("book_author" ,mData.get(pos).getAuthors());
i.putExtra("book_title" ,mData.get(pos).getItems().get(pos).getVolumeInfo().getmAuthors());
// i.putExtra("book_desc" ,mData.get(pos).getDescription());
i.putExtra("book_title" ,mData.get(pos).getItems().get(pos).getVolumeInfo().getmDescription());
// i.putExtra("book_categories" ,mData.get(pos).getCategories());
i.putExtra("book_title" ,mData.get(pos).getItems().get(pos).getVolumeInfo().getmCategories());
// i.putExtra("book_publish_date" ,mData.get(pos).getPublishedDate());
i.putExtra("book_title" ,mData.get(pos).getItems().get(pos).getVolumeInfo().getmPublishedDate());
// i.putExtra("book_info" ,mData.get(pos).getmUrl());
// i.putExtra("book_buy" ,mData.get(pos).getBuy());
// i.putExtra("book_preview" ,mData.get(pos).getPerview());
// i.putExtra("book_thumbnail" ,mData.get(pos).getThumbnail());
i.putExtra("book_title" ,mData.get(pos).getItems().get(pos).getVolumeInfo().getmImageLinks().getmThumbnail());
// i.putExtra("volumeInfo" ,mData.get(pos).getVolumeInfo());
// Log.d(LOG_TAG, "onClick: " + mData.get(pos).getVolumeInfo());
mContext.startActivity(i);
}
});
return viewHolder;
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int i) {
Book2 book = mData.get(i); // <-- Tried this.
Book2.VolumeInfo book = mData.get(i).getItems().get(i).getVolumeInfo(); // <-- Tried this
holder.tvTitle.setText(book.getItems().get(i).getVolumeInfo().getmTitle()); // <-- Error occurs here
}
@Override
public int getItemCount() {
return mData.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder{
ImageView ivThumbnail;
TextView tvTitle, tvCategory, tvPrice, tvAuthor;
LinearLayout container;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
ivThumbnail = itemView.findViewById(R.id.thumbnail);
tvTitle = itemView.findViewById(R.id.title);
tvAuthor = itemView.findViewById(R.id.author);
tvCategory = itemView.findViewById(R.id.category);
tvPrice = itemView.findViewById(R.id.price);
container = itemView.findViewById(R.id.container);
}
}
}