RecyclerView (Custom Adapter) not refreshing the List on search - java

this is my first question on Stackoverflow. I have very recently started Android Development.
What I want to do:
I have a list of people and I want to filter/Search the RecyclerView (using Custom Adapter) list (Initial List) based on user input in the search box, in my toolbar(not ActionBar).
My Problem:
Initially, nothing was happening. The list was not changing at all. Now, the list changes, but only one fixed list item (Current Search output) gets displayed no matter what the input. My recycler adapter is not refreshing to the new filtered list. And I am not getting any errors in the bulid or the logcat.
What I have tried:
After debugging for a whole day, and fixing some "NullPointerExceptions" in my Layout Manager and the RecycleView adapter and having tried 2 different method for filtering. Even though I am able to generate a filtered array (List values in Logcat) I am not able to get the results. I tried using , the "notifyDataSetChanged()", "notifyItemRangeChanged()" and "*notifyAll();, but all in vain....
Please help.....
public class MainActivity extends AppCompatActivity {
ArrayList<Consultant> consultants= new ArrayList<>();
ArrayList<Consultant> allConsultants = new ArrayList<>();
int rating=5;
int price = 10000;
String categoryFilter;
String ratingFilter;
RecyclerView recyclerView;
Consultant_RecyclerAdapter.RecyclerViewClickListener listener;
Consultant_RecyclerAdapter adapter= new Consultant_RecyclerAdapter(consultants,listener);
Spinner s_categories;
Spinner s_rating;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
recyclerView= findViewById(R.id.RecycleView);
s_categories=findViewById(R.id.Spinner_Category);
s_rating=findViewById(R.id.Spinner_Rating);
addToList();
setUpAdapter();
}
private void setUpAdapter() {
Log.i("Adapter","Started");
setOnClickListener();
Consultant_RecyclerAdapter adapter = new Consultant_RecyclerAdapter(consultants,listener);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
Log.i("Adapter","Ended");
}
private void addToList(){
consultants.add(new Consultant("Dr Kapoor", "consultant_id", "profilePic_src", new String[]{"Dentist","Dermatology"}, 1000, 5));
consultants.add(new Consultant("Dr Pankaj Kumar", "consultant_id", "profilePic_src", new String[]{"Psychology","Respiratory"}, 3000, 1));
consultants.add(new Consultant("Dr Harsh Jha", "consultant_id", "profilePic_src", new String[]{"Internal Medicine"}, 1500, 5));
consultants.add(new Consultant("Dr Gaurav Singh", "consultant_id", "profilePic_src", new String[]{"Dentist","Cardiologist"}, 3500, 4));
consultants.add(new Consultant("Dr Aman", "consultant_id", "profilePic_src", new String[]{"Lungs","Neuro"}, 1000, 2));
consultants.add(new Consultant("Dr Jatin Chabra", "consultant_id", "profilePic_src", new String[]{"Psychology"}, 5000, 3));
Log.i("List","Done");
allConsultants=new ArrayList<>(consultants);
}
private void setOnClickListener() {
listener = new Consultant_RecyclerAdapter.RecyclerViewClickListener() {
#Override
public void onClick(View v, int position) {
Intent intent = new Intent(getApplicationContext(), ConsultantProfileActivity.class);
intent.putExtra("consultant_name", consultants.get(position).getName());
intent.putExtra("pic_src", consultants.get(position).getProfilePic_src());
intent.putExtra("about", consultants.get(position).getAbout());
intent.putExtra("consultant_id",consultants.get(position).getConsultant_id());
intent.putExtra("categories",consultants.get(position).getCategories());
startActivity(intent);
}
};
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.search, menu);
MenuItem menuItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) menuItem.getActionView();
searchView.setQueryHint("Search....");
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
Log.i("Search","QueryChanged");
//adapter.getFilter().filter(newText);
filter(newText);
return false ;
}
});
return true;
}
private void filter(String text) {
// creating a new array list to filter our data.
ArrayList<Consultant> filteredlist = new ArrayList<>();
// running a for loop to compare elements.
for (Consultant item : allConsultants) {
Log.i("Filter: ",item.getName()+"...."+text);
// checking if the entered string matched with any item of our recycler view.
if (item.getName().toLowerCase().contains(text.toLowerCase())) {
Log.i("Match","Found");
// if the item is matched we are
// adding it to our filtered list.
filteredlist.add(item);
}
}
Log.i("Filter: ",(filteredlist.toString()));
if (filteredlist.isEmpty()) {
// if no item is added in filtered list we are
// displaying a toast message as no data found.
Toast.makeText(this, "No Data Found..", Toast.LENGTH_SHORT).show();
} else {
// at last we are passing that filtered
// list to our adapter class.
adapter.filterList(filteredlist);
}
}
}
Please, ignore the search method in the following Recycler Adapter, I am currently using the search method in the mainActivity
public class Consultant_RecyclerAdapter extends RecyclerView.Adapter<Consultant_RecyclerAdapter.MyViewHolder>{
ArrayList consultants;
ArrayList AllConsultants,preFilteredList;
private RecyclerViewClickListener listener;
public Consultant_RecyclerAdapter(ArrayList<Consultant> consultants, RecyclerViewClickListener listener) {
this.consultants = consultants;
this.listener = listener;
//AllConsultants = new ArrayList<>(consultants);
//preFilteredList = new ArrayList<>(consultants);
}
//NOTIFYING THE ADAPTER ABOUT UPDATE
public void filterList(ArrayList<Consultant> filteredlist) {
consultants.clear();
consultants.addAll(filteredlist);
notifyDataSetChanged();
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView name, rating, price, category;
private ImageView profile;
public MyViewHolder(#NonNull View view) {
super(view);
name = view.findViewById(R.id.textView_Name);
profile = view.findViewById(R.id.imageView_ProfilePic);
category = view.findViewById(R.id.textView_Category);
rating = view.findViewById(R.id.textView_Rating);
price = view.findViewById(R.id.textView_Price);
view.setOnClickListener(this);
}
#Override
public void onClick(View view) {listener.onClick(view, getAdapterPosition()); }
}
#NonNull
#Override
public Consultant_RecyclerAdapter.MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.consultant_list_item, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
String name = consultants.get(position).getName();
String profilePic_src = consultants.get(position).getProfilePic_src();
float rating = consultants.get(position).getRating();
String categories = "";
//Converting Array to string
for (String i : consultants.get(position).getCategories()) {
categories = i + ", " + categories;
}
int price = consultants.get(position).getPrice();
holder.name.setText(name);
holder.category.setText(categories);
holder.price.setText(String.valueOf(price));
holder.rating.setText(String.valueOf(rating));
holder.profile.setImageResource(R.drawable.consultant);}
#Override
public int getItemCount() {
return consultants.size();
}
public interface RecyclerViewClickListener {
void onClick(View v, int position);
}
public void listUpdate(String categoryFilter, String ratingFilter) {
preFilteredList = new ArrayList<>();
if (categoryFilter != null || ratingFilter != null) {
for (Consultant item : AllConsultants) {
if (String.valueOf(item.getRating()).toLowerCase(Locale.ROOT).contains(ratingFilter) && item.getCategories().toString().toLowerCase(Locale.ROOT).contains(categoryFilter)) {
preFilteredList.add(item);
}
}
}else{
preFilteredList= new ArrayList<Consultant>(AllConsultants);
}
consultants.clear();
consultants.addAll(preFilteredList);
getFilter();
}
#Override
public Filter getFilter() {
return theFilter;
}
public Filter theFilter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
List<Consultant> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
filteredList.addAll(AllConsultants);
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (Consultant item : AllConsultants) {
Log.i("Filter: ",item.getName()+"...."+filterPattern);
if (item.getName().toLowerCase().contains(filterPattern)) {
Log.i("Match","Found");
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
Log.i("Filter ","Published");
consultants.clear();
consultants.addAll((List) results.values);
notifyDataSetChanged();
}
};
}

Do not Use Activity To filter the Results this kinda degrade the performance . use Filterable interface in Adapter it performs filtering on a background thread and post the result on Main thread. Which you already implemented i see .
By looking at your code of adapter i think it should work because you are maintaining different references for Both list complete and filtered .
The main culprit i thing is You have initialized Adapter as Global variable but the adapter you are setting to RecyclerView is a another one which you have created locally . Fix this and it should work .
private Consultant_RecyclerAdapter adapter ; // Global variable
private void setUpAdapter() {
Log.i("Adapter","Started");
setOnClickListener();
adapter = new Consultant_RecyclerAdapter(consultants,listener);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
Log.i("Adapter","Ended");
}

Related

How can filter recyclerview in selected viewpager fragment on search?

I have 3 tab fragments in viewpager with tabs. All tabs have recyclerview with ListAdapter showing customers list. Each tab represents 1) all customers 2) New ordered customers 3) Paid customers. I want to set search filter only on tab selected fragment. If the Searchview can place on activity which is common for all fragments, will be better in my case. I tried several ways but was failed. My search was resulting always only in last tab (Paid). Please can any one help me with full example of code ?
And my MainActivity
private void initializeTab(){
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
viewPager = (MyViewPager) findViewById(R.id.view_pager);
viewPager.setOffscreenPageLimit(5);
viewPager.setAdapter(mSectionsPagerAdapter);
tabLayout = (SmartTabLayout) findViewById(R.id.tabs);
tabLayout.setViewPager(viewPager);
viewPager.setPagingEnabled(true);
}
private class SectionsPagerAdapter extends FragmentStatePagerAdapter {
protected int currentPosition = -1;
protected Fragment currentFragment;
public SectionsPagerAdapter(FragmentManager fm) {
super(fm,BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
}
#Override
public Fragment getItem(int position) {
return ViewPagerFragment.newInstance(getPageTitle(position)+"");
}
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "All";
case 1:
return "New";
case 2:
return "Paid";
}
return null;
}
#Override
public void setPrimaryItem(#NonNull ViewGroup container, int position, #NonNull Object object) {
super.setPrimaryItem(container, position, object);
this.currentPosition = position;
if (object instanceof Fragment){
this.currentFragment = (Fragment)object;
}
}
public Fragment getCurrentFragment() {
return currentFragment;
}
public void setCurrentFragment(Fragment currentFragment) {
this.currentFragment = currentFragment;
}
}
and my Fragment
public class ViewPagerFragment extends AbstractFragment {
............
public static ViewPagerFragment newInstance(String title) {
ViewPagerFragment fragment = new ViewPagerFragment();
Bundle args = new Bundle();
args.putString("TITLE",title);
fragment.setArguments(args);
return fragment;
}
#Override
public void onViewCreated(final View view, Bundle savedInstanceState) {
swipeLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeToRefresh);
recycler = (RecyclerView) view.findViewById(R.id.recycler);
adapter = new CustomerAdapter(getContext());
recycler.setLayoutManager(new LinearLayoutManager(getContext()));
recycler.setHasFixedSize(true);
recycler.addItemDecoration(new ItemDecoration(1,false, dpToPx(0),true,2));
recycler.setItemAnimator(new DefaultItemAnimator());
recycler.setAdapter(adapter);
changeFragment(swipeLayout);
}
public void changeFragment(final SwipeRefreshLayout swipeLayout){
final String tab = getArguments().getString("TITLE");
loadDatas(allRecords,tab);
swipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
swipeLayout.setRefreshing(true);
utils.getDetails(getContext());
utils.setOnDataLoaded(new MyUtils.DataLoadingListener() {
#Override
public void onDataLoaded(ArrayList<Customers> list) {
loadDatas(list, tab);
swipeLayout.setRefreshing(false);
}
});
}
});
// Scheme colors for animation
swipeLayout.setColorSchemeColors(
getResources().getColor(android.R.color.holo_blue_bright),
getResources().getColor(android.R.color.holo_green_light),
getResources().getColor(android.R.color.holo_orange_light),
getResources().getColor(android.R.color.holo_red_light)
);
}
void loadDatas(List<Customers> list, String tab){
if (list != null && list.size() > 0) {
List<Customers> tabList = new ArrayList<>();
if (tab.equals("All")) {
tabList = list;
}else {
for (Customers item : list) {
if (item.getStatus().equals(tab)) {
tabList.add(item);
}else {
Log.d(TAG, "loadDatas: "+item.getStatus());
}
}
}
adapter.submitList(tabList);
}
}
}
the Searchview can place on activity which is common for all fragments, will be better in my case.
This is right.
I tried several ways but was failed. My search was resulting always only in last tab (Paid).
So, I'm assuming that the issue now isn't in the filtering itself, but that it always returns the results of the last tab; and therefore you probably didn't provide the filtering code for such a reason.
Now we've 3 tabs in the ViewPager, each represents a fragment; So we need to get the current selected fragment of the ViewPager in order to allow the activity send it the searched text.
To get the current fragment from ViewPager (Your case):
ViewPagerFragment currentFragment = (ViewPagerFragment) mViewPagerAdapter.instantiateItem(viewPager, viewPager.getCurrentItem());
To get the current fragment from ViewPager2:
The ViewPager has getCurrentItem() which returns the current page number
So, we need to link the each page fragment to the page number.
But we can get a ViewPager fragment by its id (item id), so the first step is to have page Ids that equals to the corresponding position, to do so override getItemId in the ViewPager adapter.
#Override
public long getItemId(int position) {
return position;
}
Then in the activity filtering part assuming you are searching for a String that is in a var named seachString:
int pageId = viewpager.getCurrentItem();
Fragment currentFragment = (ViewPagerFragment) getChildFragmentManager()
.findFragmentByTag("f" + pageId);
Then after getting the current fragment, create some method in it that accepts a String parameter for the searched value:
So, in ViewPagerFragment, create:
public void searchFor(String search) {
// filter the results of the RecyclerView
}
And call that method on the current fragment of the ViewPager in the activity:
currentFragment.searchFor(seachString);
About the recyclerview filter data:
could make your class CustomerAdapter implements Filterable
like :
class Adapter extends RecyclerView.Adapter implements Filterable {
......
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
return ...;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
}
};
}
}
could also refer this:https://github.com/xaverkapeller/Searchable-RecyclerView-Demo
About how to do this in selected viewpager fragment , you just need to invoke the search method of the current fragment.
At last I succeeded, I think it is not very professional but it is working fine. To help some one suffering I am sharing that here.
Firstly I added tabScrollingListener to get the selected fragment in MainActivity
public class MainActivity extends AppCompatActivity{
..........
private ViewPagerFragment selectedFragment;
private void initializeTab(){
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
viewPager = (MyViewPager) findViewById(R.id.view_pager);
viewPager.setOffscreenPageLimit(5);
viewPager.setAdapter(mSectionsPagerAdapter);
tabLayout = (SmartTabLayout) findViewById(R.id.tabs);
tabLayout.setViewPager(viewPager);
viewPager.setPagingEnabled(true);
viewPager.setCurrentItem(0);
tabLayout.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
selectedFragment = (ViewPagerFragment) mSectionsPagerAdapter.getCurrentFragment();
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
}
Then I transferred my filter function to Fragment like mentioned in Zain's answer. As I am using ListAdapter for my recycler it's easy to submit my filter list to adapter. I loaded my filter list on loadData function.
public class ViewPagerFragment extends AbstractFragment {
............
private List<Customers> filterList;
public static ViewPagerFragment newInstance(String title) {
ViewPagerFragment fragment = new ViewPagerFragment();
Bundle args = new Bundle();
args.putString("TITLE",title);
fragment.setArguments(args);
return fragment;
}
#Override
public void onViewCreated(final View view, Bundle savedInstanceState) {
swipeLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeToRefresh);
recycler = (RecyclerView) view.findViewById(R.id.recycler);
adapter = new CustomerAdapter(getContext());
recycler.setLayoutManager(new LinearLayoutManager(getContext()));
recycler.setHasFixedSize(true);
recycler.addItemDecoration(new ItemDecoration(1,false, dpToPx(0),true,2));
recycler.setItemAnimator(new DefaultItemAnimator());
recycler.setAdapter(adapter);
changeFragment(swipeLayout);
}
public void changeFragment(final SwipeRefreshLayout swipeLayout){
final String tab = getArguments().getString("TITLE");
loadDatas(allRecords,tab);
swipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
swipeLayout.setRefreshing(true);
utils.getDetails(getContext());
utils.setOnDataLoaded(new MyUtils.DataLoadingListener() {
#Override
public void onDataLoaded(ArrayList<Customers> list) {
loadDatas(list, tab);
swipeLayout.setRefreshing(false);
}
});
}
});
// Scheme colors for animation
swipeLayout.setColorSchemeColors(
getResources().getColor(android.R.color.holo_blue_bright),
getResources().getColor(android.R.color.holo_green_light),
getResources().getColor(android.R.color.holo_orange_light),
getResources().getColor(android.R.color.holo_red_light)
);
}
void loadDatas(List<Customers> list, String tab){
if (list != null && list.size() > 0) {
List<Customers> tabList = new ArrayList<>();
if (tab.equals("All")) {
tabList = list;
}else {
for (Customers item : list) {
if (item.getStatus().equals(tab)) {
tabList.add(item);
}else {
Log.d(TAG, "loadDatas: "+item.getStatus());
}
}
}
filterList = tabList; // this fills filter list
adapter.submitList(tabList);
}
}
}
public void filter(String text, String filter) {
ArrayList<Customers> filteredlist = new ArrayList<>();
// running a for loop to compare elements.
if (filterList != null && filterList.size() > 0) {
if (text.length() > 0) {
for (Customers item : filterList) {
// here filter options gone
}
}else {
filteredlist.addAll(filterList);
}
}
adapter.submitList(filteredlist);
}
Yea, Now I got currentSelectedFragment with filter function in MainActivity
In searchListener I can call it like selectedFragment.filter(query).
searchview.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
selectedFragment.filter(newText); // search filter here
return true;
}
});
Follow the below step to find the clicked tab,
First add tab select listener
tabLayout.addOnTabSelectedListener(object:TabLayout.OnTabSelectedListener{
override fun onTabSelected(tab: TabLayout.Tab?) {
selectedFragment= fragmentViewPagerAdapter!!.fragments[tab!!.position]
}
override fun onTabUnselected(tab: TabLayout.Tab?) {
// enter code here
}
override fun onTabReselected(tab: TabLayout.Tab?) {
// enter code here
}
})
and then setupWithViewPager
tabLayout.setupWithViewPager(viewPager)

java.lang.NullPointerException: Attempt to invoke interface method 'java.util.Iterator java.util.List.iterator()' on a null object reference

I m currently working on a android apps which fetch data from parse server. I wanted to filter my recyclerView by using searchview. But it shows me nothing while search. It gives me error in this line*for (ParseObject parseObject : mRooms){ * Please help me to edit my code regarding this issues.
roomcardrecyclerviewadapter
private List<ParseObject> mRooms = new ArrayList<>();
private ArrayList<ParseObject> filterlist;
private ParseObject room;
private String mSection;
private Context context;
public RoomCardRecyclerViewAdapter(){
super(DIFF_CALLBACK);
}
public static final DiffUtil.ItemCallback<ParseObject> DIFF_CALLBACK = new
DiffUtil.ItemCallback<ParseObject>() {
#Override
public boolean areItemsTheSame(#NonNull ParseObject oldItem, #NonNull ParseObject newItem) {
return oldItem.getObjectId() == newItem.getObjectId();
}
#Override
public boolean areContentsTheSame(#NonNull ParseObject oldItem, #NonNull ParseObject newItem) {
return (oldItem.getUpdatedAt().equals(newItem.getUpdatedAt()) &&
oldItem.getCreatedAt().equals(newItem.getCreatedAt()));
}
};
public RoomCardRecyclerViewAdapter(String section) {
this();
this.mSection = section;
}
public RoomCardRecyclerViewAdapter(Context context, List<ParseObject>arrayList) {
this();
this.context = context;
mRooms = arrayList;
filterlist = (ArrayList<ParseObject>) arrayList;
}
public class RoomViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
protected ImageView mRoomImage;
protected TextView mRoomPrice;
protected TextView mInclusiveOrNot;
protected TextView mPropertyType;
protected TextView mNumOfBeds;
protected TextView mNumOfBaths;
protected TextView mRoomLocation;
private Context context;
public RoomViewHolder(Context context, View itemView) {
super(itemView);
mRoomImage = itemView.findViewById(R.id.room_image);
mRoomPrice = itemView.findViewById(R.id.price_label);
mInclusiveOrNot = itemView.findViewById(R.id.incl_excl_label);
mPropertyType = itemView.findViewById(R.id.propertyType_label);
mNumOfBeds = itemView.findViewById(R.id.num_beds_label);
mNumOfBaths = itemView.findViewById(R.id.details_num_baths_label);
mRoomLocation = itemView.findViewById(R.id.location_label);
this.context = context;
//set onclick listener
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Log.i("Click event: ", "My room has been clicked.");
int pos = getAdapterPosition();
Intent intent;
ParseObject room = getCurrentList().get(pos);
//create the ParseObject proxy
ParseProxyObject roomProxy = new ParseProxyObject(room);
Toast.makeText(context, room.getString("roomSuburb"), Toast.LENGTH_LONG).show();
//fork to corresponding activity
if(mSection != null) {
Log.i("mSection text: ", "mSection text is: " + mSection);
if (mSection.equals("My Rooms")) {
//start my rooms detail activity
Log.i("My room: ", "Room selected " + roomProxy.getObjectId());
intent = new Intent(context, MyRoomDetailActivity.class);
//add the room to the intent
intent.putExtra("currentSelectedRoomObject", room);
Log.i("Selected room", "Put Extra, " + room);
intent.putExtra("roomObject", roomProxy);
context.startActivity(intent);
}
}else {
Log.i("My room:", "RoomDetailActivity loaded for MyRoomDetail Activity instead");
intent = new Intent(context, RoomDetailActivity.class);
//add the proxy to the intent
intent.putExtra("roomObject", roomProxy);
context.startActivity(intent);
}
}
}
#Override
public RoomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//inflating the viewholder with the appropriate views
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.room_cardview, parent,
false);
return new RoomViewHolder(parent.getContext(), view);
}
#Override
public void onBindViewHolder(#NonNull RoomViewHolder holder, int position) {
room = getItem(position);
holder.mRoomLocation.setText(room.getString("roomSuburb"));
holder.mRoomPrice.setText(Integer.toString(room.getInt("roomMonthlyRent")));
holder.mInclusiveOrNot.setText(room.getString("roomRentInclusiveOfBills"));
holder.mPropertyType.setText(room.getString("roomPropertyType"));
holder.mNumOfBeds.setText(Integer.toString(room.getInt("roomBedrooms")));
holder.mNumOfBaths.setText(Integer.toString(room.getInt("roomBathrooms")));
#Override
public Filter getFilter(){
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()){
room = (ParseObject) mRooms;
}else {
List<ParseObject> filteredList = new ArrayList<>();
for (ParseObject parseObject : mRooms){
if (parseObject.getString("roomSuburb").toLowerCase().contains(charString.toLowerCase())){
filteredList.add(parseObject);
}
}
room = (ParseObject) filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = room;
return filterResults;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
room = (ParseObject) filterResults.values;
notifyDataSetChanged();
}
};
}
mainActivity
mHomeSectionsPagerAdapter = new
HomeSectionsPagerAdapter(getSupportFragmentManager());
roomCardRecyclerViewAdapter = new RoomCardRecyclerViewAdapter(this,
mRooms);
mRooms = new ArrayList<>();
// Set up the ViewPager with the sections adapter.
mViewPager = findViewById(R.id.container);
mViewPager.setAdapter(mHomeSectionsPagerAdapter);
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
final ParseQuery<ParseUser> query = ParseUser.getQuery();
//get the search view and set the searchable configuration
SearchManager searchManager = (SearchManager)
getSystemService(Context.SEARCH_SERVICE);
MenuItem item = menu.findItem(R.id.search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
//assumes the current activity is the searchable activity
searchView.setSearchableInfo(searchManager.getSearchableInfo
(getComponentName());
searchView.setSubmitButtonEnabled(true);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
roomCardRecyclerViewAdapter.getFilter().filter(query);
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
roomCardRecyclerViewAdapter.getFilter().filter(newText);
return false;
}
});
return true;
}
#Override
public boolean onSearchRequested() {
//pauseSomeStuff();
//roomCardRecyclerViewAdapter.getFilter().filter(query);
return super.onSearchRequested();
}
I think problem is here:
You haven't shared first lines of MainActivity where you declare your variables. So, I assume that you have some code like this:
List mRooms;
Then I assume that, before assigning value to this mRooms you have passed it to RoomCardRecyclerViewAdapter:
roomCardRecyclerViewAdapter = new RoomCardRecyclerViewAdapter(this, mRooms);
mRooms = new ArrayList<>();
Then you have assigned value to mRooms. That's why you get NPE. You can solve this problem just like this:
mRooms = new ArrayList<>();
roomCardRecyclerViewAdapter = new RoomCardRecyclerViewAdapter(this, mRooms);

Filtering in RealmRecyclerViewAdapter does not hide excluded elements

I'm currently building an app which use a RealmRecyclerViewAdapter for displaying the elements inside Realm.
I was looking into implementing the Filterable interface, which I managed to do (thanks to those answers: Link 1 Link 2) but now I have a side effect: when I'm filtering, the Adapter shows all the elements, even if they doesn't match with the filter. Also, the excluded element does show incorrect information. When I close the SearchView, everything is back to normal.
Here is the Activity when I call the Adapter:
public class MainActivity extends AppCompatActivity {
private Realm realm;
HabitCardAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
setUIMode();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set the title inside the top bar for this activity.
// I'm not doing it inside the Manifest because it changes the app's name
setTitle(R.string.MainActivityTitle);
// Bottom App Bar setup
BottomAppBar bottomAppBar = findViewById(R.id.bottomAppBar);
cutBottomAppEdge(bottomAppBar); // Diamond shape
// Add listener to Stats button inside the bottom app bar
MenuItem statsMenuItem = bottomAppBar.getMenu().findItem(R.id.statsMenuItem);
statsMenuItem.setOnMenuItemClickListener(item -> {
if(item.getItemId() == R.id.statsMenuItem){
Intent i = new Intent(getApplicationContext(), StatsActivity.class);
startActivity(i);
return true;
}
return false;
});
// FAB button setup
FloatingActionButton fab = findViewById(R.id.fabAddButton);
fab.setOnClickListener(view -> {
Intent intent = new Intent(getBaseContext(), CreateHabitActivity.class);
startActivity(intent);
});
RecyclerView rv = findViewById(R.id.habitCardRecyclerView);
TextView emptyMessage = findViewById(R.id.mainEmptyHabitListMessage);
realm = Realm.getDefaultInstance();
RealmResults<Habit> results = realm.where(Habit.class).sort("id").findAll();
results.addChangeListener(habits -> {
if (habits.size() > 0) {
rv.setVisibility(View.VISIBLE);
emptyMessage.setVisibility(View.GONE);
} else {
emptyMessage.setVisibility(View.VISIBLE);
rv.setVisibility(View.GONE);
}
});
//this is necessarily because it is not changed yet
if (results.size() > 0) {
rv.setVisibility(View.VISIBLE);
emptyMessage.setVisibility(View.GONE);
} else {
emptyMessage.setVisibility(View.VISIBLE);
rv.setVisibility(View.GONE);
}
final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
rv.setLayoutManager(layoutManager);
adapter = new HabitCardAdapter(results, true, this, realm);
rv.setAdapter(adapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.top_app_bar_menu, menu);
SearchView searchView = (SearchView) menu.findItem(R.id.searchMenuItem).getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
adapter.getFilter().filter(query);
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
if (adapter != null) {
adapter.getFilter().filter(newText);
return true;
}
return false;
}
});
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.searchMenuItem:
return true;
case R.id.settingMenuItem:
Intent intent = new Intent(getApplicationContext(), SettingsActivity.class);
startActivity(intent); //FIXME: animazione
return true;
case R.id.aboutMenuItem:
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
builder.setTitle(getString(R.string.about_us_title));
builder.setMessage(getString(R.string.about_us_message));
builder.setIcon(R.drawable.ic_sprout_fg_small);
builder.setPositiveButton("OK", (dialogInterface, i) -> {
dialogInterface.dismiss();
});
builder.show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/**
* Set the Night/Light UI. On the first run of the app, the user get the Light UI.
*/
private void setUIMode() {
SharedPreferences preferences = getSharedPreferences(SettingsActivity.SHARED_PREFS_FILE, MODE_PRIVATE);
int pref = preferences.getInt(SettingsActivity.SHARED_PREFS_DARK_MODE, AppCompatDelegate.MODE_NIGHT_NO);
AppCompatDelegate.setDefaultNightMode(pref);
}
private void cutBottomAppEdge(BottomAppBar bar) {
BottomAppBarTopEdgeTreatment topEdge = new SproutBottomAppBarCutCornersTopEdge(
bar.getFabCradleMargin(),
bar.getFabCradleRoundedCornerRadius(),
bar.getCradleVerticalOffset());
MaterialShapeDrawable babBackground = (MaterialShapeDrawable) bar.getBackground();
//It requires 1.1.0-alpha10
babBackground.setShapeAppearanceModel(
babBackground.getShapeAppearanceModel()
.toBuilder()
.setTopEdge(topEdge)
.build());
}
#Override
protected void onDestroy() {
super.onDestroy();
realm.removeAllChangeListeners();
realm.close();
}
}
Here is the HabitCardAdapter which extends RealmRecyclerViewAdapter:
public class HabitCardAdapter extends RealmRecyclerViewAdapter<Habit, HabitCardAdapter.ViewHolder> implements Filterable {
Context ct;
OrderedRealmCollection<Habit> list;
Realm mRealm;
public HabitCardAdapter(#Nullable OrderedRealmCollection<Habit> data, boolean autoUpdate, Context context, Realm realm) {
super(data, autoUpdate); //autoUpdate to true
ct = context;
list = data;
mRealm = realm;
}
#Override
public int getItemCount() {
return this.list.size();
}
#NonNull
#Override
public HabitCardAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
//TODO: inflatare diversi tipi di carte a seconda del habitType
View view = inflater.inflate(R.layout.fragment_habit_counter_card, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull HabitCardAdapter.ViewHolder holder, int position) {
final Habit habit = getItem(position);
if (habit != null) {
holder.setHabit(habit);
holder.editHabitButton.setOnClickListener(view -> {
Intent intent = new Intent(ct, EditHabitActivity.class);
intent.putExtra("HABIT_ID", habit.getId());
//TODO: Aggiungere l'animazione
ct.startActivity(intent);
});
holder.checkButton.setOnClickListener(view -> {
int habitId = habit.getId();
int newRepValue = habit.getRepetitions() + 1;
int maxReps = habit.getMaxRepetitions();
Log.d("Testing", newRepValue + " - " + maxReps);
if (newRepValue <= habit.getMaxRepetitions()) {
habit.getRealm().executeTransaction(realm -> {
Habit result = realm.where(Habit.class).equalTo("id", habitId).findFirst();
if (result != null) {
result.setRepetitions(newRepValue);
String newLabel = "Completato " + newRepValue + " volte su " + maxReps;
holder.progressLabel.setText(newLabel);
}
});
}
});
}
}
public void filterResults(String text) {
text = text == null ? null : text.toLowerCase().trim();
if (text == null || "".equals(text)) {
updateData(mRealm.where(Habit.class).sort("id").findAllAsync());
} else {
updateData(mRealm.where(Habit.class).contains("title", text).sort("id").findAllAsync());
}
}
public Filter getFilter() {
HabitFilter filter = new HabitFilter(this);
return filter;
}
private class HabitFilter extends Filter {
private final HabitCardAdapter adapter;
private HabitFilter(HabitCardAdapter adapter) {
this.adapter = adapter;
}
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
return new FilterResults();
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
adapter.filterResults(charSequence.toString());
}
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView habitTitle;
ProgressBar progressBar;
TextView progressLabel;
ImageButton editHabitButton;
Button checkButton;
public ViewHolder(#NonNull View itemView) {
super(itemView);
habitTitle = itemView.findViewById(R.id.habitCardTitle);
editHabitButton = itemView.findViewById(R.id.counterHabitEditButton);
progressBar = itemView.findViewById(R.id.counterHabitProgressBar);
checkButton = itemView.findViewById(R.id.checkButton);
progressLabel = itemView.findViewById(R.id.counterHabitProgressLabel);
}
void setHabit(Habit habit) {
this.habitTitle.setText(habit.getTitle());
this.progressBar.setProgress(habit.getRepetitions());
this.progressBar.setMax(habit.getMaxRepetitions());
this.progressLabel.setText("Completato " + habit.getRepetitions() + " volte su " + habit.getMaxRepetitions()); //FIXME: sposta la stringa
}
}
}
I don't really know if this is the way to go for this problem, but it's now behaving as expected so I'll share the solution here.
Inside the HabitCardAdapter I added another OrderedRealmCollection<Habit> member, called filteredList, while list holds the whole data. In the costructor both of filteredList and list are tied to the data passed to the constructor, but while filteredList will be modified by the query, list will not (probably putting it to final is the best practice). Then everything in the Adapter will now reference to filteredList instead of list, and when the SearchView is selected and the query is up, filteredList will get the data, and then updateData(filteredList) will be called.
Here is what I changed:
public class HabitCardAdapter extends RealmRecyclerViewAdapter<Habit, HabitCardAdapter.ViewHolder> implements Filterable {
Context ct;
OrderedRealmCollection<Habit> list;
OrderedRealmCollection<Habit> filteredList;
Realm mRealm;
...
}
public HabitCardAdapter(#Nullable OrderedRealmCollection<Habit> data, Context context, Realm realm) {
super(data, true, true);
ct = context;
list = data;
filteredList = data;
mRealm = realm;
setHasStableIds(true);
}
Probably the error was here in getItemCount(), when the filteredListsize was smaller than the list one, but since I didn't have any reference to filteredList, I didn't have any way to change that size, and so the Adapter would continue to show - for example - 6 views while I was querying for 3. Having it as a properly class member it let me make this:
#Override
public int getItemCount() {
return this.filteredList.size();
}
public void filterResults(String text) {
text = text == null ? null : text.toLowerCase().trim();
if (text == null || "".equals(text)) {
filteredList = list;
} else {
filteredList = mRealm.where(Habit.class).beginsWith("title", text, Case.INSENSITIVE).sort("id").findAll();
}
updateData(filteredList);
}

How to load data into recyclerView

In my application i want get some data from server and show into recyclerView. For application architecture i used MVP
I wrote below codes, but after loaded data from server, not show any data into recyclerView!
I used debug mode and show me data in this break point
public void add(List<DataItem> list) {
list.addAll(list);
notifyDataSetChanged();
}
but not show me data into recyclerView!
My Activity codes :
public class ListFragment extends Fragment implements ActiveTestsContract.View {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_tester_active_tests, container, false);
//Initialize
init();
//User token log
if (!App.isEmptyString(App.getPrefs("JWT")) || !App.getPrefs("JWT").equals(ConstKeys.EMPTY)) {
userToken = App.getPrefs("JWT");
}
//Load data
getData();
return view;
}
#Override
public void updateTestsList(Data data, int page) {
testerDashboard_emptyLay.setVisibility(View.GONE);
activeTests_pullToLoader.setVisibility(View.VISIBLE);
//Get lasted page
if (page == data.getLastPage()) {
isHasLoadedAll = true;
activeTests_pullToLoader.setComplete();
}
adapter.add(data.getData());
//Complete items
isLoading = false;
nextPage = page + 1;
activeTests_pullToLoader.setComplete();
}
#Override
public void init() {
context = getActivity();
handler = new Handler(Looper.getMainLooper());
testsPresenter = new ActiveTestsPresenter(this, 3);
testerDashboard_loader = view.findViewById(R.id.testerDashboard_loader);
activeTests_pullToLoader = view.findViewById(R.id.activeTests_pullToLoader);
testerDashboard_emptyLay = view.findViewById(R.id.testerDashboard_emptyLay);
emptyLayout_editProfileBtn = view.findViewById(R.id.emptyLayout_editProfileBtn);
layoutManager = new LinearLayoutManager(context);
recyclerView = activeTests_pullToLoader.getRecyclerView();
//Adapter
adapter = new TesterActiveRecyclerAdapter(activeModel, context);
//Init recycler and adapter
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
activeTests_pullToLoader.setColorSchemeResources(R.color.colorPrimary);
}
private void getData() {
activeTests_pullToLoader.isLoadMoreEnabled(true);
activeTests_pullToLoader.setPullCallback(new PullCallback() {
#Override
public void onLoadMore() {
isLoading = true;
//Call api
testsPresenter.testsListResponse(App.recipesApi, userToken, nextPage);
}
#Override
public void onRefresh() {
adapter.clear();
isHasLoadedAll = false;
isLoading = true;
//Call api
testsPresenter.testsListResponse(App.recipesApi, userToken, 1);
}
#Override
public boolean isLoading() {
return isLoading;
}
#Override
public boolean hasLoadedAllItems() {
return isHasLoadedAll;
}
});
activeTests_pullToLoader.initLoad();
}
Adapter codes:
public class TesterActiveRecyclerAdapter extends RecyclerView.Adapter<TesterActiveRecyclerAdapter.ViewHolder> {
private List<DataItem> list;
private Context context;
public TesterActiveRecyclerAdapter(List<DataItem> list, Context context) {
this.list = list;
this.context = context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_tester_test_list, parent, false);
return new ViewHolder(view);
}
#SuppressLint("SetTextI18n")
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
DataItem item = list.get(position);
//Name
holder.txt_name.setText(item.getTitle());
//Conditions
if (!App.isEmptyString(item.getOs()) && !App.isEmptyString(item.getType()) && !App.isEmptyString(item.getBrowser())) {
holder.txt_condition.setText(item.getType() + " | " + item.getOs() + " | " + item.getBrowser());
}
//Button actions
holder.setState(item.getState(), position);
//Price
holder.rowTests_priceTxt.setText(item.getPrice() + " Dollar");
//Animate items
Animation animation = AnimationUtils.loadAnimation(App.context,
(position > list.size() - 1) ? R.anim.down_from_top : R.anim.up_from_bottom);
holder.itemView.startAnimation(animation);
Toast.makeText(context, ""+list.get(0).getId(), Toast.LENGTH_SHORT).show();
}
#Override
public int getItemCount() {
return list.size();
}
public void add(List<DataItem> list) {
list.addAll(list);
notifyDataSetChanged();
}
public void clear() {
list.clear();
notifyDataSetChanged();
}
class ViewHolder extends RecyclerView.ViewHolder {
private ViewGroup root;
private TextView txt_name, txt_value, txt_condition, rowTests_priceTxt;
private RoundTextView rowTests_button;
ViewHolder(View view) {
super(view);
root = (ViewGroup) view;
txt_name = view.findViewById(R.id.txtTestListTitle);
txt_value = view.findViewById(R.id.txtTestListSublist);
txt_condition = view.findViewById(R.id.txtTestListSublist2);
rowTests_priceTxt = view.findViewById(R.id.rowTests_priceTxt);
rowTests_button = view.findViewById(R.id.rowTests_button);
}
}
How can i fix it?
You are adding data again in the same list passed in the parameter. Try to replace the below code
public void add(List<DataItem> list) {
list.addAll(list);
notifyDataSetChanged();
}
with
public void add(List<DataItem> list) {
this.list.addAll(list);
notifyDataSetChanged();
}
Clear the current list
Add the data to the adapter's list.
public void add(List<DataItem> list) {
clear();
this.list.addAll(list);
notifyDataSetChanged();
}
Your approach didn't work because you were updating the very list that you were passing in the function and not the adapter's list.
First add all data into list & than notify your adapter , after this set your adapter to recyclerview.
list.addAll(data)
adapter.notifyDataSetChanged()
val layoutManager = LinearLayoutManager(activity)
recyclerview.isNestedScrollingEnabled = false
recyclerview.layoutManager = layoutManager
recyclerview.itemAnimator = DefaultItemAnimator()
recyclerview.adapter = mAdapter

How to clear the recyclerview / adapter in searchview for next search android

I am using retrofit to search the images and displaying. I am using SearchView to search and recyclerview and adapter to display the item.
It's working for the very first time. Second time when I search, it's displaying the same item. It's not clearing the view to display.
Here is my code:
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getName();
ImagesViewModel newsViewModel;
List<Hits> newsArticles;
List<Hits> articleArrayList;
ImagesAdapter newsAdapter;
RecyclerView rvHeadline;
SearchView searchView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rvHeadline = (RecyclerView) findViewById(R.id.rvNews);
searchView=(SearchView) findViewById(R.id.searchView);
searchView.setQueryHint("Search Images");
searchView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
searchView.setIconified(false);
}
});
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
callPixabayImages(query);
Toast.makeText(getBaseContext(), query, Toast.LENGTH_LONG).show();
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
callPixabayImages(newText);
Toast.makeText(getBaseContext(), newText, Toast.LENGTH_LONG).show();
return false;
}
});
articleArrayList = new ArrayList<>();
}
private void callPixabayImages(String query){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ImageApiInterface.PIXABAY_URL)
.addConverterFactory(GsonConverterFactory.create()) //Here we are using the GsonConverterFactory to directly convert json data to object
.build();
ImageApiInterface api = retrofit.create(ImageApiInterface.class);
Call<MyImages> call = api.getMovieDetails(query);
call.enqueue(new Callback<MyImages>() {
#Override
public void onResponse(Call<MyImages> call, Response<MyImages> response) {
Log.e("response","response"+response.code());
if(response.isSuccessful()){
Log.e("response","response"+response.code());
if((response.body() != null ? response.body().getHits() : null) !=null){
List<Hits> imagesList = response.body().getHits();
articleArrayList.addAll(imagesList);
newsAdapter.notifyDataSetChanged();
}
}
}
#Override
public void onFailure(Call<MyImages> call, Throwable t) {
System.out.println("Error: "+ t.getMessage());
Log.e("response","response"+t);
}
});
}
private void setupRecyclerView() {
if (newsAdapter == null) {
newsAdapter = new ImagesAdapter(MainActivity.this, articleArrayList);
rvHeadline.setLayoutManager(new LinearLayoutManager(this));
rvHeadline.setAdapter(newsAdapter);
rvHeadline.setItemAnimator(new DefaultItemAnimator());
rvHeadline.setNestedScrollingEnabled(true);
} else {
newsAdapter.notifyDataSetChanged();
}
}
Here where I need to reset to search the new item inorder to avoid to display the previous item. List is not clearing to display the new items.
Here is Adapter class:
public class ImagesAdapter extends RecyclerView.Adapter<ImagesAdapter.NewsViewHolder> {
private Context context;
private List<Hits> articles;
public ImagesAdapter(Context context, List<Hits> articles) {
this.context = context;
this.articles = articles;
}
#NonNull
#Override
public ImagesAdapter.NewsViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.images_item, parent, false);
return new NewsViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ImagesAdapter.NewsViewHolder holder, final int position) {
String image = articles.get(position).getLargeImageURL();
Log.e("imagestest",image);
if (image != null) {
Glide.with(context) //passing context
.load(image) //passing your url to load image.
.dontAnimate()
.placeholder(context.getDrawable(R.drawable.image_not_available)) //this would be your default image (like default profile or logo etc). it would be loaded at initial time and it will replace with your loaded image once glide successfully load image using url.
//.centerCrop()//this method help to fit image into center of your ImageView
.into(holder.ivNews); //pass imageView reference to appear the image.*/
}
}
#Override
public int getItemCount() {
return articles.size();
}
class NewsViewHolder extends RecyclerView.ViewHolder {
ImageView ivNews;
private NewsViewHolder(#NonNull View itemView) {
super(itemView);
ivNews = itemView.findViewById(R.id.ivNews);
}
}
}
I am clueless where exactly I need to clear the view to fetch the newly searched item.
Trial 1: I tried to clear the list object articleArrayList but it throws crash that adapter size is null.
Clean the
articleArrayList
before loading the searched items again.... by executing this line articleArrayList.clear();
public void onResponse(Call<MyImages> call, Response<MyImages> response) {
Log.e("response","response"+response.code());
if(response.isSuccessful()){
Log.e("response","response"+response.code());
if((response.body() != null ? response.body().getHits() : null) !=null){
List<Hits> imagesList = response.body().getHits();
articleArrayList.clear();
articleArrayList.addAll(imagesList);
newsAdapter.notifyDataSetChanged();
}
}
You're adding generated imagesList to the articleArrayList, you should be replacing the values.
articleArrayList = imagesList;

Categories