Ben
Ben

Reputation: 1849

recycleview setadapter for specific position

I have created a "horizontal listview" by using Recycleview.

Since I have async task in my program I cannot retrieve from fetchbook class the book result and therefore I need to set the adapter inside the class.

My code looks as follows:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate( savedInstanceState );
    setContentView( R.layout.activity_main );


    ArrayList<String> names = new ArrayList<>();
    names.add("szF_pLGmJTQC");
    names.add("QTKD3-mMZFYC");

    for (int i = 0; i<names.size(); i++){
        fetchBooks(names.get( i ));

    }

}


private void fetchBooks(String query) {

    client = new MyBookClient();
    final ArrayList<String> authors = new ArrayList<>(  );
    final ArrayList<String> titles = new ArrayList<>(  );
    final ArrayList<String> image = new ArrayList<>(  );
    MyBook books = new MyBook();
    client.getBooks( query, new JsonHttpResponseHandler(){
        @Override
        public void onSuccess(int statusCode, Header[] headers, JSONObject response){
            if(response!=null){
                MyBook books = MyBook.fromJson(response);

                authors.add(books.getAuthor());
                titles.add(books.getTitle());
                image.add(books.getCoverUrl());

                RecyclerView recyclerView = findViewById(R.id.rvAnimals);
                LinearLayoutManager horizontalLayoutManager
                        = new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, false);
                recyclerView.setLayoutManager(horizontalLayoutManager);
                adapter = new MyRecyclerViewAdapter(MainActivity.this, authors, titles,image);
                adapter.setClickListener(MainActivity.this);
                recyclerView.setAdapter(adapter);

                Toast.makeText(MainActivity.this, "You clicked " + books.getAuthor(), Toast.LENGTH_SHORT).show();
            }
        }
    });
}

However, it causes the adapter to clean the previous view and add on it the current.

The code of the adapter is added below:

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {

    private List<String> mViewAuthor;
    private List<String> mTitles;
    private List<String> mimages;
    private LayoutInflater mInflater;
    private ItemClickListener mClickListener;
    private Context mContext;

    MyRecyclerViewAdapter(Context context, List<String> authors, List<String> titles, List<String> image) {
        this.mInflater = LayoutInflater.from(context);
        this.mViewAuthor = authors;
        this.mTitles = titles;
        this.mimages = image;
        this.mContext = context;
    }

    @Override
    @NonNull
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = mInflater.inflate( R.layout.recyclerview_item, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

        String color = mViewAuthor.get(position);
        String animal = mTitles.get(position);
        String image = mimages.get( position);
        holder.tvAuthor.setText(color);
        holder.tvTitle.setText(animal);

        Picasso.with(mContext).load(Uri.parse(image)).error(R.drawable.ic_nocover).into(holder.ivBookCover);
    }

    @Override
    public int getItemCount() {
        return mViewAuthor.size();
    }

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        TextView tvAuthor;
        TextView tvTitle;
        ImageView ivBookCover;

        ViewHolder(View itemView) {
            super(itemView);
            tvAuthor = itemView.findViewById(R.id.tvAuthor);
            tvTitle = itemView.findViewById(R.id.tvTitle);
            ivBookCover = itemView.findViewById(R.id.ivBookCover);
            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
        }
    }

    public String getItem(int id) {
        return mViewAuthor.get(id);
    }

    public void setClickListener(ItemClickListener itemClickListener) {
        this.mClickListener = itemClickListener;
    }

    // parent activity will implement this method to respond to click events
    public interface ItemClickListener {
        void onItemClick(View view, int position);
    }

}

and the code of MyBook is:

public class MyBook implements Serializable {
    private String author;
    private String title;
    private String bookid;
    private String rating;

    public String getTitle() {
        return title;
    }

    public String getAuthor() {
        return author;
    }

    public String getId() {
        return bookid;
    }

    public String getRating(){
        return rating;
    }


    public static MyBook fromJson(JSONObject jsonObject) {
        MyBook book = new MyBook();
        try {

            JSONObject volumeInfo = jsonObject.getJSONObject( "volumeInfo" );
            book.title = volumeInfo.has("title") ? volumeInfo.getString("title") : "";
            book.author = getAuthor(volumeInfo);
            book.bookid = jsonObject.has("id") ? jsonObject.getString("id") : "";
            book.rating = volumeInfo.has("averageRating") ? String.valueOf(volumeInfo.getDouble("averageRating")) : "0";
        } catch (JSONException e) {
            e.printStackTrace();
            return null;
        }
        return book;
    }

    private static String getAuthor(final JSONObject jsonObject) {
        try {
            final JSONArray authors = jsonObject.getJSONArray("authors");
            int numAuthors = authors.length();
            final String[] authorStrings = new String[numAuthors];
            for (int i = 0; i < numAuthors; ++i) {
                authorStrings[i] = authors.getString(i);
            }
            return TextUtils.join(", ", authorStrings);
        } catch (JSONException e) {
            return "";
        }
    }

}

Is there any way that I call setadapter I will also define the position where I want to view to be added?

something like:

fetchBooks(names.get( i ), i);

where the second parameter i is the position inside the adapter so I could get in position i=0 the first result then at i=1 the second result.

or is there just a way I can return books from fetchBooks class?

Thank you

Upvotes: 0

Views: 265

Answers (1)

Zain
Zain

Reputation: 40898

However, it causes the adapter to clean the previous view and add on it the current.

As I understand that you are trying to add query results into your RecyclerView list, but the problem is that it removes the old/previous query result from the list while adding the new one. and you need to keep all the results. Please correct me if that is wrong.

This behavior might be due to instantiating new adapter each time you get a new query result inside onSucess() method. So you can avoid that by transfering this part of code into onCreate() method; and then for each onSuccess() call, you can just call adapter.notifyDataSetChanged() to notify the adapter that it source of data is changed, so update yourself.

This also requires us not to instantiate the adapter with new data, but just add new method to the adapter to update lists with .addAll() method.

So changes:

MyRecyclerViewAdapter adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate( savedInstanceState );
    setContentView( R.layout.activity_main );

    ArrayList<String> names = new ArrayList<>();
    names.add("szF_pLGmJTQC");
    names.add("QTKD3-mMZFYC");

    RecyclerView recyclerView = findViewById(R.id.rvAnimals);
    LinearLayoutManager horizontalLayoutManager
            = new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, false);
    recyclerView.setLayoutManager(horizontalLayoutManager);
    adapter = new MyRecyclerViewAdapter(MainActivity.this, new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
    adapter.setClickListener(MainActivity.this);
    recyclerView.setAdapter(adapter);


    for (int i = 0; i<names.size(); i++){
        fetchBooks(names.get( i ));
    }

}


private void fetchBooks(String query) {

    client = new MyBookClient();
    MyBook books = new MyBook();
    client.getBooks( query, new JsonHttpResponseHandler(){
        @Override
        public void onSuccess(int statusCode, Header[] headers, JSONObject response){
            if(response!=null){
                MyBook books = MyBook.fromJson(response);

                adapter.addBooks(books.getAuthor(), books.getTitle(), books.getCoverUrl());

                Toast.makeText(MainActivity.this, "You clicked " + books.getAuthor(), Toast.LENGTH_SHORT).show();
            }
        }
    });
}

and add below method to adapter code

public void addBook(String author, String title, String image) {
    this.mViewAuthor.add(author);
    this.mTitles.add(title);
    this.mimages.add(image);
    this.notifyDataSetChanged();
}

I am all welcome if you need further help

Upvotes: 1

Related Questions