Recyclerview onViewScrolled called multiple times - java

Currently working on recyclerview that refreshes every time I choose something.
Everytime I would set again the adapter after I selected a choice.
For example, if I choose Fruit, the recyclerview will change to fruits.
I would attach a new adapter to the recyclerview everytime.
The problem with this is whenever I check on onViewScrolled, it is getting called the same amount as I changed the recyclerview data.
My question is, why does this occurs ? Is it because the old adapter didn't detach ?
If yes, how do I detach it properly ?

I think you have a problem with the recycler adapter class. For example, you change some data and scroll down. When your scroll is up and that shows your old data.
Add this code in the adapter class.
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}

Related

Reload recyclerview

I am new to android and I am having a problem reloading (rebuilding) as recyclerview after the activity is active. The activity with the recyclerview is a second activity started as an intent on the main activity. I can load it up, and show a list of items. When one of the items is clicked a third activity is launched. The problem is sometimes there are too many items on the list. I want to add a way of selecting an item more easily. I added a spinner on the same activity as the recyclerview. When an item is selected on the spinner, I want to reload a shorter version of the list, based on the spinner selection. However, I can't find a way to achieve that. Any help or suggestions pointing me in the right direction will be greatly appreciated.
as #bink said without code it's hard to help, but the idea in general is that on your spinner.setOnItemSelectedListener() you populate your recyclerView, so everytime you change the selection you get a new list depending on the choosed value.
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
ArrayList<> arrayList = new ArrayList<>();
// add your items based on item spinner.itemSelected
// for(---)
adapter = new MyAdapter(context, arrayList );
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
});
You can also add a filter to your recycler view (https://medium.com/android-news/filterable-recyclerview-in-android-the-how-to-a9ade9cd26)
If you dont want to recreate all the recycler view and the list itselft, use adapter.notifyDataSetChanged();

Execute code from Spinner's onItemSelected that's in custom listView

I have a custom listView with 3 spinners. I want to execute a code in onItemSelcted but I cannot do this in adapter because some part of the code that I need to execute won't work in a adapter.
I had this code pinned to a button before but sometimes there are over 20-30 elements in the list and I need do this "automaticly" right after user picks a value from spinner to save some time.
For a button I had this code:
((ListView) parent).performItemClick(v, position, 0);
in setOnClickListener that I created inside adapter. After using this code in adapter I could exetue any code outside adapter by writing something like this:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
long viewId = view.getId();
if(viewId == R.id.button){
myCode(); }
I found no way to do something similar because there was no "link" between inside adapter onItemSelcted and outside adapter onItemSelcted. Of course writing same line of code inside adapter's onItemSelcted won't work because spinner "doesn't click".
Any idea how to solve this?
In a fewer words: I need to execute onItemSelected for a spinner that's inside custom listView element but need to do this outside the adapter in onCreate method.
You can create an CallbackInterface and create an instance of it "outside" and pass it down to the "inside", where you call the callback function with the needed arguments.
public interface Callback {
void onAction (int a, int b, String c);
}

Refreshing a RecyclerView when all items are removed

I have a RecyclerView that shows a list of items.
If there is no item to show, The recyclerview shows one item with a specific view (to tell the user there is no item instead of a white screen).
Within HistoryFragment:
private void initRecyclerView(Boolean isNoResult){
HistoryRecyclerViewAdapter adapter = new HistoryRecyclerViewAdapter(mContext, mRecords, **isNoResult**);
mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext));
mRecyclerView.setAdapter(adapter);
}
Within HistoryRecyclerViewAdapter:
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view;
if(**isEmpty**) {
**view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_listitem_prhistory_empty, parent, false);**
} else {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_listitem_prhistory, parent, false);
}
ViewHolder holder = new ViewHolder(view);
return holder;
}
So, it's possible to remove items one by one, if we click on them.
I would like to set isEmpty to true and refresh the RecyclerView when the dataSet is null.
I already know where to call that method but I really don't know how I can do that? (i.e. refresh the RecyclerView with isEmpty = true so I can display the cell that explain to the user that there is no record anymore).
Don't inflate different view-holders, because when the adapter has no items, not a single one of them will ever be inflated. Instead one can wrap the RecyclerView together with a "no data" Fragment into a ViewFlipper, which then can be switched to the Fragment, when the RecyclerView adapter has no items.
Best practice is to use an empty view outside of RecyclerView but in case you like to do what you want:
1.in onCreateViewHolder only inflate one layout which has empty and item views
on item delete check if your array is empty and then add a null item
then in onBindViewHolder check the model if model is Null visible empty view otherwise show item view
summary:
onBind:
model is null : empty View visible
model is not null: item View visible
use interface to refresh the RecyclerView after remove something like this
public interface RefreshRecyclerView {
public void Refresh();
}
then in activity or fragment implement the interface
Fragment implements RefreshRecyclerView
you will have override method like this
#Override
public void Refresh() {
// set adapter again here
}
then pass the interface to adapter like this
RefreshRecyclerView refresh = (RefreshRecyclerView) this;
yourRecycler.setadapter(refresh);
fially when user clicked on adapter use this
refresh. Refresh();

Custom ListView in a fragment, what files do I need?

I already created this with custom adapter in another project, but I didn't use fragments. I now have a project using fragments, and am displaying the listview in a fragment. I don't know or am able to find exactly what rules and what classes/java files I need for this to work in a fragment.
Every example on the internet I've used develops an error in some way, and since I don't understand every aspect of how this is done I can't fix it on my own.
In my previous project, I did this (CalculationsActivity.java):
public class CalculationsActivity extends AppCompatActivity implements Serializable {
//content of my class
}
class CustomAdapter extends BaseAdapter {
#Override
public int getCount() {
return arrayLi.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
view = getLayoutInflater().inflate(R.layout.customlayout, null);
ImageView imageView = (ImageView) view.findViewById(R.id.imageView);
TextView content = (TextView) view.findViewById(R.id.content);
TextView date = (TextView) view.findViewById(R.id.date);
imageView.setImageResource(R.drawable.calcer);
String[] convertedArrLi = arrayLi.toArray(new String[arrayLi.size()]);
String[] convertedDates = dates.toArray(new String[dates.size()]);
content.setText(convertedArrLi[i]);
date.setText(convertedDates[i]);
return view;
}
}
And from that I set an adapter to my listview. This class was in the same java file as the activity that the listview was displayed in. If I do this in my fragment, I get a bunch of red lines. getLayoutInflater() and variables from my other class above it will be red.
As I understand so far you need MainActivity.java, MyFragment.java and Adapter.java. To make your listview work with your array you need to set an adapter including the current activity and the array you want to use. If someone can explain what files I actually need and how they work together (send info to each other and start one another), I would appreciate it.
Note: I have to use a custom adapter.
You can use your custom adapter in activity and in fragment, there is no difference. Can you provide screenshot of your bunch of red lines?
Also your question is incorrect: "what files do I need?". You need classes, first class for activity or fragment to create/declare/initialize second class (custom adapter) and fill it with data.

Adding views to PagerAdapter too slow

My method add views to PagerAdapter:
public void initdata() {
for(int i = 0;i<=1189;i++){
view = inflater.inflate(R.layout.testss,null);
tx = (TextView)view.findViewById(R.id.txts);
tx.setText(textseries[i]));
pageList.add(tx);}
}
My pagerAdapter:
#Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(pageList.get(position));
return pageList.get(position);}
it takes 5~6 sec add views to PagerAdapter , but the TextView is just change it's content,how to avoid call view method so much times ?
how to avoid call view method so much times ?
The best solution would be to replace ViewPager with RecyclerView, so that pages can get recycled.
The next-best solution is to work out some PagerAdapter that can manage recycling of your pages.
The solution closest to what you have is:
Step #1: Get rid of initdata()
Step #2: Get rid of pageList()
Step #3: Inflate the layout and set the text on the TextView in instantiateItem(), so you only need to do it for pages that the user visits, and then only on demand

Categories