I trying to do Expandable Recyclerview but have a bug Android/Java - java

I try to implement expandable RecyclerView as shown in this example :
https://github.com/CodingSTUFF070/Nested-RecyclerView-Inside-Expandable-RecyclerView
But I have bug :
When I implement the same for my app. Steps to reproduce - Click 1st item (Instant Food and Noodles) and scroll to last and click last item (Personal Care) without closing 1st opened item. Now, if you scroll-up and see the child items of 1st parent, you'll see child items of lastly opened parent (Personal Care).
Please tell me how to fix this?
MainActivity:
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private List<DataModel> mList;
private ItemAdapter adapter;
private Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.main_recyclervie);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
mList = new ArrayList<>();
//list1
List<String> nestedList1 = new ArrayList<>();
nestedList1.add("Jams and Honey");
nestedList1.add("Pickles and Chutneys");
nestedList1.add("Readymade Meals");
nestedList1.add("Chyawanprash and Health Foods");
nestedList1.add("Pasta and Soups");
nestedList1.add("Sauces and Ketchup");
nestedList1.add("Namkeen and Snacks");
nestedList1.add("Honey and Spreads");
List<String> nestedList2 = new ArrayList<>();
nestedList2.add("Book");
nestedList2.add("Pen");
nestedList2.add("Office Chair");
nestedList2.add("Pencil");
nestedList2.add("Eraser");
nestedList2.add("NoteBook");
nestedList2.add("Map");
nestedList2.add("Office Table");
List<String> nestedList3 = new ArrayList<>();
nestedList3.add("Decorates");
nestedList3.add("Tea Table");
nestedList3.add("Wall Paint");
nestedList3.add("Furniture");
nestedList3.add("Bedsits");
nestedList3.add("Certain");
nestedList3.add("Namkeen and Snacks");
nestedList3.add("Honey and Spreads");
List<String> nestedList4 = new ArrayList<>();
nestedList4.add("Pasta");
nestedList4.add("Spices");
nestedList4.add("Salt");
nestedList4.add("Chyawanprash");
nestedList4.add("Maggie");
nestedList4.add("Sauces and Ketchup");
nestedList4.add("Snacks");
nestedList4.add("Kurkure");
List<String> nestedList5 = new ArrayList<>();
nestedList5.add("Jams and Honey");
nestedList5.add("Pickles and Chutneys");
nestedList5.add("Readymade Meals");
nestedList5.add("Chyawanprash and Health Foods");
nestedList5.add("Pasta and Soups");
nestedList5.add("Sauces and Ketchup");
nestedList5.add("Namkeen and Snacks");
nestedList5.add("Honey and Spreads");
List<String> nestedList6 = new ArrayList<>();
nestedList6.add("Pasta");
nestedList6.add("Spices");
nestedList6.add("Salt");
nestedList6.add("Chyawanprash");
nestedList6.add("Maggie");
nestedList6.add("Sauces and Ketchup");
nestedList6.add("Snacks");
nestedList6.add("Kurkure");
List<String> nestedList7 = new ArrayList<>();
nestedList7.add("Decorates");
nestedList7.add("Tea Table");
nestedList7.add("Wall Paint");
nestedList7.add("Furniture");
nestedList7.add("Bedsits");
nestedList7.add("Certain");
nestedList7.add("Namkeen and Snacks");
nestedList7.add("Honey and Spreads");
mList.add(new DataModel(nestedList1 , "Instant Food and Noodles"));
mList.add(new DataModel( nestedList2,"Stationary"));
mList.add(new DataModel( nestedList3,"Home Care"));
mList.add(new DataModel(nestedList4 ,"Grocery & Staples"));
mList.add(new DataModel(nestedList5,"Pet Care"));
mList.add(new DataModel(nestedList6,"Baby Care"));
mList.add(new DataModel(nestedList7 ,"Personal Care"));
adapter = new ItemAdapter(mList);
recyclerView.setAdapter(adapter);
}
}
DataModel:
public class DataModel {
private List<String> nestedList;
private String itemText;
private boolean isExpandable;
public DataModel(List<String> itemList, String itemText) {
this.nestedList = itemList;
this.itemText = itemText;
isExpandable = false;
}
public void setExpandable(boolean expandable) {
isExpandable = expandable;
}
public List<String> getNestedList() {
return nestedList;
}
public String getItemText() {
return itemText;
}
public boolean isExpandable() {
return isExpandable;
}
}
ItemAdapter:
public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ItemViewHolder> {
private List<DataModel> mList;
private List<String> list = new ArrayList<>();
public ItemAdapter(List<DataModel> mList){
this.mList = mList;
}
#NonNull
#Override
public ItemViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.each_item , parent , false);
return new ItemViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ItemViewHolder holder, int position) {
DataModel model = mList.get(position);
holder.mTextView.setText(model.getItemText());
boolean isExpandable = model.isExpandable();
holder.expandableLayout.setVisibility(isExpandable ? View.VISIBLE : View.GONE);
if (isExpandable){
holder.mArrowImage.setImageResource(R.drawable.arrow_up);
}else{
holder.mArrowImage.setImageResource(R.drawable.arrow_down);
}
NestedAdapter adapter = new NestedAdapter(list);
holder.nestedRecyclerView.setLayoutManager(new LinearLayoutManager(holder.itemView.getContext()));
holder.nestedRecyclerView.setHasFixedSize(true);
holder.nestedRecyclerView.setAdapter(adapter);
holder.linearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
model.setExpandable(!model.isExpandable());
list = model.getNestedList();
notifyItemChanged(holder.getAdapterPosition());
}
});
}
#Override
public int getItemCount() {
return mList.size();
}
public class ItemViewHolder extends RecyclerView.ViewHolder{
private LinearLayout linearLayout;
private RelativeLayout expandableLayout;
private TextView mTextView;
private ImageView mArrowImage;
private RecyclerView nestedRecyclerView;
public ItemViewHolder(#NonNull View itemView) {
super(itemView);
linearLayout = itemView.findViewById(R.id.linear_layout);
expandableLayout = itemView.findViewById(R.id.expandable_layout);
mTextView = itemView.findViewById(R.id.itemTv);
mArrowImage = itemView.findViewById(R.id.arro_imageview);
nestedRecyclerView = itemView.findViewById(R.id.child_rv);
}
}
}
NestedAdapter:
public class NestedAdapter extends RecyclerView.Adapter<NestedAdapter.NestedViewHolder> {
private List<String> mList;
public NestedAdapter(List<String> mList){
this.mList = mList;
}
#NonNull
#Override
public NestedViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.nested_item , parent , false);
return new NestedViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull NestedViewHolder holder, int position) {
holder.mTv.setText(mList.get(position));
}
#Override
public int getItemCount() {
return mList.size();
}
public class NestedViewHolder extends RecyclerView.ViewHolder{
private TextView mTv;
public NestedViewHolder(#NonNull View itemView) {
super(itemView);
mTv = itemView.findViewById(R.id.nestedItemTv);
}
}
}

Related

Show data in Nested Recyclerview in android

As I fetched and show the dates (see image) as the title of the main recyclerview. I want to show the available slots data instead of the 0 1 2 etc elements. The code is attached below
Url for json data
https://run.mocky.io/v3/c9bd7858-0e41-422f-b1d2-cd490c08583b
AppointmentTimeActivity.java
public class AppointmentTimeActivity extends AppCompatActivity {
SharedPrefManager sharedPrefManager;
Button appointmentTimeButton;
private TextView doctorFullName;
ConstraintLayout constraintLayout;
public static List<List<String>> availableSlots;
RecyclerView rvGroup;
public static ArrayList<String> arrayListGroup;
LinearLayoutManager layoutManagerGroup;
GroupAdapter groupAdapter;
private DoctorScheduleResponse timings;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.select_appointment_time);
getSupportActionBar().setTitle("Appointment time");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
sharedPrefManager = new SharedPrefManager(this);
constraintLayout = findViewById(R.id.constraintLayout);
appointmentTimeButton = findViewById(R.id.book_video_call_appointment_btn);
doctorFullName = findViewById(R.id.doctor_full_name);
rvGroup = findViewById(R.id.rv_group);
String docName = getIntent().getStringExtra("doctorFullName");
doctorFullName.setText(docName);
arrayListGroup = new ArrayList<>();
fetchAndShowAppointmentsTime();
}
private void fetchAndShowAppointmentsTime() {
String id = String.valueOf(SpecialityActivity.doctorID);
Call<DoctorScheduleResponse> call = RetrofitClient.getInstance().getMyInterface().getAppointmentTime("Bearer " + sharedPrefManager.getAccessToken(), id);
call.enqueue(new Callback<DoctorScheduleResponse>() {
#Override
public void onResponse(#NotNull Call<DoctorScheduleResponse> call, #NotNull Response<DoctorScheduleResponse> response) {
arrayListGroup = new ArrayList<>();
if (response.isSuccessful()) {
assert response.body() != null;
for (List<Slot> slots : response.body().getSlot()) {
for (Slot slot : slots) {
arrayListGroup.add(slot.getScheduleDate());
}
}
groupAdapter = new GroupAdapter(AppointmentTimeActivity.this, response.body().getSlot());
layoutManagerGroup = new LinearLayoutManager(getApplicationContext());
rvGroup.setLayoutManager(layoutManagerGroup);
rvGroup.setAdapter(groupAdapter);
}
}
#Override
public void onFailure(#NotNull Call<DoctorScheduleResponse> call, #NotNull Throwable t) {
Toast.makeText(getBaseContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
DoctorScheduleResponse.java
public class DoctorScheduleResponse {
#SerializedName("slot")
#Expose
private List<List<Slot>> slot = null;
public List<List<Slot>> getSlot() {
return slot;
}
public void setSlot(List<List<Slot>> slot) {
this.slot = slot;
}
}
GroupAdater.java
public class GroupAdapter extends RecyclerView.Adapter<GroupAdapter.ViewHolder> {
private Activity activity;
ArrayList<String> arrayListGroup, arrayListMember;
LinearLayoutManager linearLayoutManager;
SharedPrefManager sharedPrefManager;
List<List<Slot>> slotsList;
public GroupAdapter(Activity activity, ArrayList<String> arrayListGroup) {
this.activity = activity;
this.arrayListGroup = arrayListGroup;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.custom_slot_layout, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.dummyTV.setText(arrayListGroup.get(position));
arrayListMember = new ArrayList<>();
sharedPrefManager = new SharedPrefManager(activity);
for (int i = 0; i < 5; i++) {
arrayListMember.add(String.valueOf(i));
}
CustomAdapter customAdapter = new CustomAdapter(arrayListMember);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(activity);
holder.rvMember.setLayoutManager(linearLayoutManager);
holder.rvMember.setAdapter(customAdapter);
}
#Override
public int getItemCount() {
return arrayListGroup.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView dummyTV;
RecyclerView rvMember;
public ViewHolder(#NonNull View itemView) {
super(itemView);
dummyTV = itemView.findViewById(R.id.dummyTextView);
rvMember = itemView.findViewById(R.id.rv_member);
}
}
}
CustomAdapter.java
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.SlotsViewHolder> {
ArrayList<String> slots;
public CustomAdapter(ArrayList<String> slots) {
this.slots = slots;
}
#NonNull
#Override
public SlotsViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.available_slots_list, parent, false);
return new CustomAdapter.SlotsViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull SlotsViewHolder holder, int position) {
holder.tvSlots.setText(slots.get(position));
}
#Override
public int getItemCount() {
return slots.size();
}
public class SlotsViewHolder extends RecyclerView.ViewHolder {
TextView tvSlots;
public SlotsViewHolder(#NonNull View itemView) {
super(itemView);
tvSlots = itemView.findViewById(R.id.tv_slots);
}
}
}
Nested recycler view will be more complex in terms of memory. So you can achieve same UI with different approach.
You should try with single recycler view with dynamic layout binding.
Example: For single item of recycler view, there will be a header(for date) and a viewgroup(may be linear layout) then bind any no. of child views inside that linear layout.
The problem is in GroupAdater.java. Inside onBindViewHolder method you are adding the value of loop variable to your list that you pass to your nested recycler view adaptor.
for (int i = 0; i < 5; i++) {
arrayListMember.add(String.valueOf(i));
}
You have to add the correct date from arrayListGroup object.

RecyclerView onClick returns false item

i have a RecyclerView and an EditText, when the search is typed it will filter out the items. but when the search is clicked it just passes the first unfiltered search. here is my code.
here is the FoodAdapter..
public class FoodAdapter extends RecyclerView.Adapter<FoodAdapter.ProductViewHolder> {
private Context mCtx;
private static List<FoodModel> productList;
private OnNoteListener monNoteListener;
//getting the context and product list with constructor
public FoodAdapter(Context mCtx, List<FoodModel> productList, OnNoteListener onNoteListener) {
this.mCtx = mCtx;
this.productList = productList;
this.monNoteListener = onNoteListener;
}
public void filteredList(List<FoodModel> filteredList) {
productList = filteredList;
notifyDataSetChanged();
}
#Override
public ProductViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//inflating and returning our view holder
LayoutInflater inflater = LayoutInflater.from(mCtx);
View view = inflater.inflate(R.layout.sam_layout_products, null);
return new ProductViewHolder(view,monNoteListener);
}
#Override
public void onBindViewHolder(ProductViewHolder holder, int position) {
//getting the product of the specified position
FoodModel product = productList.get(position);
//binding the data with the viewholder views
holder.txtFoodName.setText(product.getFoodName());
holder.txtFoodDesc.setText(product.getFoodDesc());
holder.txtFoodPrice.setText(product.getFoodPrice());
holder.imageView.setImageDrawable(mCtx.getResources().getDrawable(product.getFoodImage()));
}
#Override
public int getItemCount() {
return productList.size();
}
public class ProductViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView txtFoodName, txtFoodDesc, txtFoodPrice;
ImageView imageView;
OnNoteListener onNoteListener;
public ProductViewHolder(View itemView, OnNoteListener onNoteListener) {
super(itemView);
txtFoodName = itemView.findViewById(R.id.txtFood);
txtFoodDesc = itemView.findViewById(R.id.txtFoodDesc);
txtFoodPrice = itemView.findViewById(R.id.txtFoodPrice);
imageView = itemView.findViewById(R.id.imageView);
this.onNoteListener = onNoteListener;
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
onNoteListener.onNoteClick(getAdapterPosition());
}
}
public interface OnNoteListener{
void onNoteClick(int position);
}
}
and here is the activity FoodActivity
public class FoodsActivity extends AppCompatActivity implements FoodAdapter.OnNoteListener {
private DrawerLayout dl;
private ActionBarDrawerToggle t;
private NavigationView nv;
static List<FoodModel> FoodList;
static List<FoodModel> filteredList;
//the recyclerview
RecyclerView recyclerView;
String NameString;
FoodAdapter foodAdapter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.foods_layout);
setTitle("Foods");
RecyclerViewFood();
EditText txtFoodSearch = findViewById(R.id.txtFoodSearch);
txtFoodSearch.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence query, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
SearchFilter(editable.toString());
}
});
}
#Override
public void onNoteClick(int position) {
Intent intent = new Intent(this, sample_layout.class);
intent.putExtra("foods", FoodList.get(position));
startActivity(intent);
}
private void SearchFilter(String text){
recyclerView = (RecyclerView) findViewById(R.id.FoodRecyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
filteredList = new ArrayList<>();
for(FoodModel item: FoodList){
if(item.getFoodName().toLowerCase().contains(text.toLowerCase())){
filteredList.add(item);
}
}
foodAdapter = new FoodAdapter(this,filteredList,this);
// what can i do to pass the correct item to the next intent
recyclerView.setAdapter(foodAdapter);
}
public void RecyclerViewFood() {
recyclerView = (RecyclerView) findViewById(R.id.FoodRecyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
FoodList = new ArrayList<>();
String food_name[] = getResources().getStringArray(R.array.food_name);
String food_desc[] = getResources().getStringArray(R.array.food_desc);
String food_price[] = getResources().getStringArray(R.array.food_price);
int food_image[] = {R.drawable.pic_chickenpizza, R.drawable.pic_dorowot, R.drawable.pic_genfo, R.drawable.pic_kitfo, R.drawable.pic_tibs};
for (int i = 0, j = 0, k = 0, l = 0; i < food_name.length; i++, j++, k++, l++) {
FoodList.add(new FoodModel(2, food_name[i], food_desc[j], food_price[k], food_image[l]));
}
//creating recyclerview adapter
foodAdapter= new FoodAdapter(this, FoodList, this);
//setting adapter to recyclerview
recyclerView.setAdapter(foodAdapter);
}
when the search is entered, it works but when the filteredList is clicked its passing the wrong item to the next intent.
First, your adapter implements Filterable.
public class FoodAdapter extends RecyclerView.Adapter<FoodAdapter.ProductViewHolder> implements Filterable {
// Filtered list
private List<FoodModel> filterList;
// Normal list
private List<FoodModel> productList;
In your constructor:
this.filterList = productList;
productList = new ArrayList<>(productList);
Implementing Filterable requires overriding the getFilter() method.
Filtering the list:
#Override
public Filter getFilter() {
return MyFilter;
}
private Filter MyFilter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
List<FoodModel> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
filteredList.addAll(productList);
} else {
String filterPattern = constraint.toString().trim();
for (FoodModel item : productList) {
if (item.getFoodName().contains(filterPattern)) {
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filterList.clear();
filterList.addAll((List) results.values);
notifyDataSetChanged();
}
};
This is important that you use the filtered list inside onBindViewHolder:
FoodModel product = filterList.get(position);
Now in your activity:
#Override
public void afterTextChanged(Editable editable) {
String newText = editable.toString();
adapter.getFilter().filter(newText);
}
Edit: get size of the filtered list instead of normal list:
#Override
public int getItemCount() {
return filterList.size();
}
In your adapter's onClick:
startMyActivity ( mCtx , filterList.get(getAdapterPosition() ).getId() );
// method
private void startMyActivity ( Activity activity , long id ) {
Intent intent = new Intent( activity , sample_layout.class);
intent.putExtra("foods", id );
activity.startActivity(intent);
}
This is in continuation for the errors you might be facing in #Prince Ali's code. Make these changes to have context passed to your intent
public class ProductViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView txtFoodName, txtFoodDesc, txtFoodPrice;
ImageView imageView;
OnNoteListener onNoteListener;
View mView; //Add this line
public ProductViewHolder(View itemView, OnNoteListener onNoteListener) {
super(itemView);
txtFoodName = itemView.findViewById(R.id.txtFood);
txtFoodDesc = itemView.findViewById(R.id.txtFoodDesc);
txtFoodPrice = itemView.findViewById(R.id.txtFoodPrice);
imageView = itemView.findViewById(R.id.imageView);
this.onNoteListener = onNoteListener;
itemView.setOnClickListener(this);
mView = itemView; // Add this line
}
Now in your onClick method
Context mCtx = holder.mView.getContext();
startMyActivity ( mCtx , filterList.get(getAdapterPosition() ).getId() );
// method
private void startMyActivity ( Context context , long id ) {
Intent intent = new Intent( context , sample_layout.class);
intent.putExtra("foods", id );
context.startActivity(intent);
}
Nevermind, i removed the old setOnClickListener and made a new one in the onBindViewHolder with the following code
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(mCtx, sample_layout.class);
intent.putExtra("foods", productList.get(position));
mCtx.startActivity(intent);}
});
and now its working.
thank you all for your answers :)

Cannot insert value in Room Database Android

I am trying to insert info about movie but I am getting this error:
java.lang.NullPointerException: Attempt to invoke virtual method 'void kawi15.myapplication.database.DatabaseViewModel.addWatchlistMovie(info.movito.themoviedbapi.model.MovieDb)' on a null object reference
I am sure that Movie is not null because I have Toast which showing me info about this movie.
I find that I need initializate DatabaseViewModel in my OnCreate():
databaseViewModel = new ViewModelProvider(this).get(DatabaseViewModel.class);
but I tried this in OnCreate and OnCreateView and in both its error with 'this':
new ViewModelProvider(this)
I try to put there getContext() or some other stuff but nothing worked here.
This is my Entity class:
#Entity
public class Watchlist {
#PrimaryKey
#ColumnInfo(name = "id")
private int movieId;
#ColumnInfo(name = "movie_title")
private String movieTitle;
#ColumnInfo(name = "poster_path")
private String posterPath;
#ColumnInfo(name = "overview")
private String overview;
#ColumnInfo(name = "release_date")
private String releaseDate;
and getters and setters for all
My Dao class:
#Dao
public interface WatchlistDao {
#Query("SELECT * FROM watchlist ORDER BY movie_title ASC")
List<Watchlist> getAll();
#Insert
void addMovie(Watchlist watchlistMovie);
}
ViewModel class:
public class DatabaseViewModel extends AndroidViewModel {
private AppDatabase db;
public DatabaseViewModel(#NonNull Application application) {
super(application);
db = AppDatabase.getDatabase(application);
}
public void addWatchlistMovie(MovieDb movieDb){
Watchlist addedMovie = new Watchlist();
addedMovie.setMovieId(movieDb.getId());
addedMovie.setMovieTitle(movieDb.getOriginalTitle());
addedMovie.setOverview(movieDb.getOverview());
addedMovie.setPosterPath(movieDb.getPosterPath());
addedMovie.setReleaseDate(movieDb.getReleaseDate());
db.watchlistDao().addMovie(addedMovie);
}
My Fragment class where I am clicking on Movie from list that I want to insert to database:
public class FragmentOne extends Fragment /*implements CustomAdapter.ListItemClickListener*/{
private static RecyclerView.Adapter adapter;
private RecyclerView.LayoutManager layoutManager;
private DatabaseViewModel databaseViewModel;
private static RecyclerView recyclerView;
private List<MovieDb> data;
//private CustomAdapter.ListItemClickListener mOnClickListener;
public static FragmentOne newInstance() {
FragmentOne fragment = new FragmentOne();
return fragment;
}
/*#Override
public void onListItemClick(int position) {
Toast.makeText(getContext(), data.get(position).getOriginalTitle(), LENGTH_SHORT).show();
}*/
public class MovieTask extends AsyncTask<Void, Void, List<MovieDb>> {
#Override
protected List<MovieDb> doInBackground(Void... voids) {
MovieResultsPage movies = new TmdbApi("f753872c7aa5c000e0f46a4ea6fc49b2").getMovies().getUpcoming("en-US", 1, "US");
List<MovieDb> listMovies = movies.getResults();
return listMovies;
}
#Override
protected void onPostExecute(List<MovieDb> movieDb) {
data = movieDb;
adapter = new CustomAdapter(data);
((CustomAdapter) adapter).setOnMovieDbClicked(movieDb2 -> {
Toast.makeText(getActivity(), movieDb2.getReleaseDate(), LENGTH_SHORT).show();
databaseViewModel.addWatchlistMovie(movieDb2);
});
recyclerView.setAdapter(adapter);
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View returnView = inflater.inflate(R.layout.fragment_one, container, false);
recyclerView = (RecyclerView) returnView.findViewById(R.id.my_recycler_view);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(getContext()); // ???
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
MovieTask mt = new MovieTask();
mt.execute();
return returnView;
}
}
and my adapter class, maybe not neccessary:
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.MyViewHolder>{
private List<MovieDb> dataSet;
private OnMovieDbClicked onMovieDbClicked;
public void setOnMovieDbClicked(OnMovieDbClicked onMovieDbClicked) {
this.onMovieDbClicked = onMovieDbClicked;
}
//final private ListItemClickListener mOnClickListener;
public class MyViewHolder extends RecyclerView.ViewHolder /*implements View.OnClickListener*/{
TextView textViewName;
TextView textViewVersion;
ImageView imageViewIcon;
//private ListItemClickListener mOnClickListener;
public MyViewHolder(View itemView) {
super(itemView);
this.textViewName = (TextView) itemView.findViewById(R.id.text1);
this.textViewVersion = (TextView) itemView.findViewById(R.id.text2);
this.imageViewIcon = (ImageView) itemView.findViewById(R.id.imageView);
itemView.setOnClickListener(view -> {
int pos = getAdapterPosition();
if (onMovieDbClicked != null && pos != RecyclerView.NO_POSITION) {
MovieDb movieDb = dataSet.get(pos);
onMovieDbClicked.movieDbClicked(movieDb);
}
});
//itemView.setOnClickListener(this);
//itemView.setOnClickListener(CustomAdapter.myOnClickListener);
}
/*#Override
public void onClick(View v) {
int position = getAdapterPosition();
mOnClickListener.onListItemClick(position);
}*/
}
public CustomAdapter(List<MovieDb> data /*ListItemClickListener mOnClickListener*/) {
this.dataSet = data;
//this.mOnClickListener = mOnClickListener;
}
public interface OnMovieDbClicked {
void movieDbClicked(MovieDb movieDb);
}
/*public interface ListItemClickListener{
void onListItemClick(int position);
}*/
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.cards_layout, parent, false);
//view.setOnClickListener(FragmentOne.myOnClickListener);
MyViewHolder myViewHolder = new MyViewHolder(view);
return myViewHolder;
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int listPosition) {
TextView textViewName = holder.textViewName;
TextView textViewVersion = holder.textViewVersion;
ImageView imageView = holder.imageViewIcon;
Glide.with(imageView).load("https://image.tmdb.org/t/p/w500" + dataSet.get(listPosition).getPosterPath()).into(imageView);
textViewName.setText(dataSet.get(listPosition).getOriginalTitle());
textViewVersion.setText(dataSet.get(listPosition).getReleaseDate());
}
#Override
public int getItemCount() {
if(dataSet == null){
return 0;
}
return dataSet.size();
}
}
You have not initialized your databaseViewModel anywhere so the NPE is expected. Make sure to fill the field before accessing it in MovieTask

How to load images from url into viewpager2?

I'm using ViewPager2 in my app to show some images it worked well when I used images from drawable but when i try to load images from links it shows error. I'm new to this so please help me how to load them from url.
It throws error at the adapter class as items.size(); refers to null.
Item Class
public class ImageSlider1_Item {
private String imageURL;
public ImageSlider1_Item(String imageURL){
this.imageURL = imageURL;
}
public String getImageURL (){
return imageURL;
}
}
Adapter Class
public class ImageSlider1_Adapter extends RecyclerView.Adapter<ImageSlider1_Adapter.ImageSlider1_ViewHolder>{
private List<ImageSlider1_Item> items;
private ViewPager2 viewPager2;
public ImageSlider1_Adapter(List<ImageSlider1_Item> items, ViewPager2 viewPager2) {
this.items = items;
this.viewPager2 = viewPager2;
}
#NonNull
#Override
public ImageSlider1_ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new ImageSlider1_ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.image_slider_layout, parent, false));
}
#Override
public void onBindViewHolder(#NonNull ImageSlider1_ViewHolder holder, int position) {
holder.setImageView(items.get(position));
}
#Override
public int getItemCount() {
return items.size();
}
class ImageSlider1_ViewHolder extends RecyclerView.ViewHolder{
private RoundedImageView imageView;
ImageSlider1_ViewHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imageSlide);
}
void setImageView(ImageSlider1_Item slider1Item){
Glide.with(itemView.getContext())
.load(slider1Item.getImageURL())
.into(imageView);
}
}
}
Main Activity
FirebaseFirestore firebaseFirestore = FirebaseFirestore.getInstance();
firebaseFirestore.collection("Image Sliders").document("Whats New").get()
.addOnSuccessListener(documentSnapshot -> {
slider1_items = new ArrayList<>();
slider1_items.add(new ImageSlider1_Item(documentSnapshot.getString("Image1")));
slider1_items.add(new ImageSlider1_Item(documentSnapshot.getString("Image2")));
slider1_items.add(new ImageSlider1_Item(documentSnapshot.getString("Image3")));
slider1_items.add(new ImageSlider1_Item(documentSnapshot.getString("Image4")));
slider1_items.add(new ImageSlider1_Item(documentSnapshot.getString("Image5")));
});
ViewPager2 viewPager2 = view.findViewById(R.id.imageSlider_1);
viewPager2.setAdapter(new ImageSlider1_Adapter(slider1_items, viewPager2));
viewPager2.setClipToPadding(false);
viewPager2.setClipChildren(false);
viewPager2.setOffscreenPageLimit(3);
viewPager2.getChildAt(0).setOverScrollMode(RecyclerView.OVER_SCROLL_NEVER);
CompositePageTransformer compositePageTransformer = new CompositePageTransformer();
compositePageTransformer.addTransformer(new MarginPageTransformer(40));
viewPager2.setPageTransformer(compositePageTransformer);
1st change your adapter like this :
public class ImageSlider1_Adapter extends RecyclerView.Adapter<ImageSlider1_Adapter.ImageSlider1_ViewHolder>{
private List<ImageSlider1_Item> items;
private Context context;
public ImageSlider1_Adapter(List<ImageSlider1_Item> items) {
this.items = items;
}
public void setItems(List<ImageSlider1_Item> items) {
this.items = items;
}
#NonNull
#Override
public ImageSlider1_ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
context = parent.getContext();
return new ImageSlider1_ViewHolder(LayoutInflater.from(context).inflate(R.layout.image_slider_layout, parent, false));
}
#Override
public void onBindViewHolder(#NonNull ImageSlider1_ViewHolder holder, int position) {
holder.setImageView(items.get(position));
}
#Override
public int getItemCount() {
return items.size();
}
class ImageSlider1_ViewHolder extends RecyclerView.ViewHolder{
private RoundedImageView imageView;
ImageSlider1_ViewHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imageSlide);
}
void setImageView(ImageSlider1_Item slider1Item){
//custom settings for fast loading image
RequestOptions options = new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
.centerCrop()
.priority(Priority.HIGH)
.format(DecodeFormat.PREFER_RGB_565);
Glide.with(context)
.applyDefaultRequestOptions(options)
.load(slider1Item.getImageURL())
.thumbnail(0.4f)
.into(imageView);
}
}
}
next in your activity
//1st initialize list & adapter
private List<ImageSlider1_Item> slider1_items = new ArrayList<>();
private ImageSlider1_Adapter adapter;
//2sd initialize views
ViewPager2 viewPager2 = view.findViewById(R.id.imageSlider_1);
viewPager2.setClipToPadding(false);
viewPager2.setClipChildren(false);
viewPager2.setOffscreenPageLimit(3);
viewPager2.getChildAt(0).setOverScrollMode(RecyclerView.OVER_SCROLL_NEVER);
CompositePageTransformer compositePageTransformer = new CompositePageTransformer();
compositePageTransformer.addTransformer(new MarginPageTransformer(40));
viewPager2.setPageTransformer(compositePageTransformer);
//3d remove ViewPager2 from adapter constructor - no need for that
//and initialize new adapter without viewPager2
adapter = new ImageSlider1_Adapter(slider1_items);
//next set adapter to ViewPager2
viewPager2.setAdapter(adapter);
FirebaseFirestore firebaseFirestore = FirebaseFirestore.getInstance();
firebaseFirestore.collection("Image Sliders").document("Whats New").get()
.addOnSuccessListener(documentSnapshot -> {
slider1_items.clear();
slider1_items.add(new ImageSlider1_Item(documentSnapshot.getString("Image1")));
slider1_items.add(new ImageSlider1_Item(documentSnapshot.getString("Image2")));
slider1_items.add(new ImageSlider1_Item(documentSnapshot.getString("Image3")));
slider1_items.add(new ImageSlider1_Item(documentSnapshot.getString("Image4")));
slider1_items.add(new ImageSlider1_Item(documentSnapshot.getString("Image5")));
//next setList to adapter
adapter.setItems(slider1_items);
adapter.notifyDataSetChanged();
});

How to handle two recyclerviews of the same layout in one activity?

I am using an MVVM structure in my project. In one activity I have two recyclerviews and one adapter. They are both using the same tasks_layout. I set the data this way:
final UnsortedAdapter adapter = new UnsortedAdapter();
eatFrog.setHasFixedSize(true);
eatFrog.setLayoutManager(new LinearLayoutManager(this));
eatFrog.setAdapter(adapter);
biologicalRhythms.setAdapter(adapter);
biologicalRhythms.setLayoutManager(new LinearLayoutManager(this));
biologicalRhythms.setHasFixedSize(true);
viewModel.getUnsortedWhereDateIs(currentDate).observe(this, new Observer<List<Unsorted>>() {
#Override
public void onChanged(List<Unsorted> unsorted) {
adapter.setData(EatAFrog(unsorted));
eatAFrogList = EatAFrog(unsorted);
adapter.setData(BiologicalRhythms(unsorted));
biologicalList = BiologicalRhythms(unsorted);
}
});
The point is that each recyclerview gets data of the same class "Unsorted", but data went through two different algorithms. If I do it this way, then two recyclerviews will have the same data, that went through second algorithm.
I tried to do different things. Firstly, I tried to use another instance of my adapter to the second recyclerview, but in that case there was no data displayed in the first recyclerview:
final UnsortedAdapter adapter = new UnsortedAdapter();
eatFrog.setHasFixedSize(true);
eatFrog.setLayoutManager(new LinearLayoutManager(this));
eatFrog.setAdapter(adapter);
final UnsortedAdapter adapter2 = new UnsortedAdapter();
biologicalRhythms.setAdapter(adapter2);
biologicalRhythms.setLayoutManager(new LinearLayoutManager(this));
biologicalRhythms.setHasFixedSize(true);
Seconly, I tried to create another adapter class, the same as third. I also created another layout - tasks2_layout, where I only changed the ids of the elements. Then in second new adapter I also changed them in a viewholder class.
My very first adapter looks like:
List<Unsorted> list = new ArrayList<>();
#NonNull
#Override
public UnsortedViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.tasks_layout , parent, false);
return new UnsortedAdapter.UnsortedViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull UnsortedViewHolder holder, int position) {
Unsorted data = list.get(position);
holder.title.setText(data.getName());
holder.date.setText(data.getDate());
holder.category.setText(String.valueOf(data.getCategory()));
holder.attach.setText(String.valueOf(data.isAttach()));
holder.to.setText(String.valueOf(toTime(data.getDuration() + data.getTimeBegin())));
holder.from.setText(String.valueOf(toTime(data.getTimeBegin())));
}
public void setData(List<Unsorted> unsortedList){
this.list = unsortedList;
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return list.size();
}
class UnsortedViewHolder extends RecyclerView.ViewHolder{
private TextView title;
private TextView date;
private TextView from;
private TextView to;
private TextView category;
private TextView attach;
public UnsortedViewHolder(#NonNull View itemView) {
super(itemView);
title = itemView.findViewById(R.id.tv_title);
date = itemView.findViewById(R.id.tv_date);
from = itemView.findViewById(R.id.tv_from2);
to = itemView.findViewById(R.id.tv_to2);
category = itemView.findViewById(R.id.tv_category);
attach = itemView.findViewById(R.id.tv_attach);
}
}
And the second, new one:
List<Unsorted> list = new ArrayList<>();
#NonNull
#Override
public UnsortedViewHolder2 onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.tasks2_layout , parent, false);
return new UnsortedAdapter2.UnsortedViewHolder2(itemView);
}
#Override
public void onBindViewHolder(#NonNull UnsortedViewHolder2 holder, int position) {
Unsorted data = list.get(position);
holder.title.setText(data.getName());
holder.date.setText(data.getDate());
holder.category.setText(String.valueOf(data.getCategory()));
holder.attach.setText(String.valueOf(data.isAttach()));
holder.to.setText(String.valueOf(toTime(data.getDuration() + data.getTimeBegin())));
holder.from.setText(String.valueOf(toTime(data.getTimeBegin())));
}
public void setData1(List<Unsorted> unsortedList){
this.list = unsortedList;
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return list.size();
}
class UnsortedViewHolder2 extends RecyclerView.ViewHolder{
private TextView title;
private TextView date;
private TextView from;
private TextView to;
private TextView category;
private TextView attach;
public UnsortedViewHolder2(#NonNull View itemView) {
super(itemView);
title = itemView.findViewById(R.id.tv_title1);
date = itemView.findViewById(R.id.tv_date1);
from = itemView.findViewById(R.id.tv_from3);
to = itemView.findViewById(R.id.tv_to3);
category = itemView.findViewById(R.id.tv_category1);
attach = itemView.findViewById(R.id.tv_attach1);
}
}
When I have set a different adapter to each of the recyclerview, nothing changed. As in previous case, only second recyclerview was showing some data.
final UnsortedAdapter adapter = new UnsortedAdapter();
eatFrog.setHasFixedSize(true);
eatFrog.setLayoutManager(new LinearLayoutManager(this));
eatFrog.setAdapter(adapter);
final UnsortedAdapter2 adapter2 = new UnsortedAdapter();
biologicalRhythms.setAdapter(adapter2);
biologicalRhythms.setLayoutManager(new LinearLayoutManager(this));
biologicalRhythms.setHasFixedSize(true);
And in onChange:
adapter.setData(EatAFrog(unsorted));
eatAFrogList = EatAFrog(unsorted);
adapter2.setData1(BiologicalRhythms(unsorted));
biologicalList = BiologicalRhythms(unsorted);
Could you please suggest how I can solve this problem? Thanks for any help.
MyViewModel class:
public class UnsortedViewModel extends AndroidViewModel {
private DatesRepository repository2;
private UnsortedRepository repository;
private SortedRepository repository3;
private LiveData<List<Unsorted>> allUnsorted;
public UnsortedViewModel(#NonNull Application application) {
super(application);
repository3 = new SortedRepository(application);
repository2 = new DatesRepository(application);
repository = new UnsortedRepository(application);
allUnsorted = repository.getAllUnsorted();
}
public LiveData<List<Unsorted>> getUnsortedWhereDateIsAlgo1(String currentDate) throws ExecutionException, InterruptedException{
return repository.getUnsortedWhereDateIs(currentDate);
}
public LiveData<List<Unsorted>> getUnsortedWhereDateIsAlgo2(String currentDate) throws ExecutionException, InterruptedException{
return repository.getUnsortedWhereDateIs(currentDate);
}
MutableLiveData<List<Unsorted>> unsortedWhereDateIsAlgo1 = new MutableLiveData<>();
MutableLiveData<List<Unsorted>> unsortedWhereDateIsAlgo2 = new MutableLiveData<>();
public void insertDate(Dates dates) {
repository2.insertDate(dates);
}
public LiveData<List<Unsorted>> getAllUnsorted() {
return allUnsorted;
}
public void insert(Unsorted data){
repository.insert(data);
}
public void deleteAllUnsorted(){
repository.deleteAllUnsorted();
}
public void deleteWhereDateIs(String currentDate){
repository.deleteWhereDateIs(currentDate);
}
public void insertSorted(Sorted data){
repository3.insertSorted(data);
}
}
Repository:
public class UnsortedRepository {
private UnsortedDao unsortedDao;
private LiveData<List<Unsorted>> allUnsorted;
public UnsortedRepository(Application application){
UnsortedDatabase database = UnsortedDatabase.getInstance(application);
unsortedDao = database.unsortedDao();
allUnsorted = unsortedDao.getAllUnsorted();
}
public LiveData<List<Unsorted>> getUnsortedWhereDateIs(String currentDate)
throws ExecutionException, InterruptedException{
return new
GetUnsortedWhereDateIsAsyncTask(unsortedDao).execute(currentDate).get();
}
private static class GetUnsortedWhereDateIsAsyncTask extends
AsyncTask<String, Void, LiveData<List<Unsorted>>> {
private UnsortedDao unsortedDao;
private GetUnsortedWhereDateIsAsyncTask(UnsortedDao unsortedDao){
this.unsortedDao = unsortedDao;
}
#Override
protected LiveData<List<Unsorted>> doInBackground(String ... strings) {
LiveData<List<Unsorted>> list =
unsortedDao.getUnsortedWhereDateIs(strings[0]);
return list;
}
}
}
Dao:
#Query ("SELECT * FROM Unsorted WHERE date = :currentDate")
LiveData<List<Unsorted>> getUnsortedWhereDateIs (String currentDate);
Your problem is, that you are observing single data source, so you will always have same data in both adapters. You need to add another LiveData inside your viewmodel. Use something like this:
unsortedWhereDateIsAlgo1 : MutableLiveData<List<Unsorted>>()
unsortedWhereDateIsAlgo2 : MutableLiveData<List<Unsorted>>()
and post result of your algorithms into correct LiveData:
fun algo1() {
//some code/operations
unsortedWhereDateIsAlgo1.postValue(result)
}
fun algo2() {
//some different code/operations
unsortedWhereDateIsAlgo2.postValue(result)
}
Next, in your fragment/activity:
viewModel.getUnsortedWhereDateIsAlgo1(currentDate).observe(this, new Observer<List<Unsorted>>() {
#Override
public void onChanged(List<Unsorted> unsorted) {
final UnsortedAdapter adapter = new UnsortedAdapter();
adapter.setData(EatAFrog(unsorted));
eatFrog.setHasFixedSize(true);
eatFrog.setLayoutManager(new LinearLayoutManager(this));
eatFrog.setAdapter(adapter);
}
});
and
viewModel.getUnsortedWhereDateIsAlgo2(currentDate).observe(this, new Observer<List<Unsorted>>() {
#Override
public void onChanged(List<Unsorted> unsorted) {
final UnsortedAdapter adapter2 = new UnsortedAdapter();
adapter2.setData(BiologicalRhythms(unsorted));
biologicalRhythms.setAdapter(adapter2);
biologicalRhythms.setLayoutManager(new LinearLayoutManager(this));
biologicalRhythms.setHasFixedSize(true);
}
});

Categories

Resources