I have a recycler view which contains different types of views. There are only 8 items in the recycler view and i don't want to recycle those views on scrolling. How to disable the recycling feature of the recycler view?
Or is there any better method to approach this?
Have you considered using ScrollView instead? You could include the different layout types you want to use inside the ScrollView, and there you would not get recycling behavior.
If that is not good enough, than I would sudgest to stick with recycler view, and not worry about views getting recycled, because it is not much of a big deal.
But if you are still convinced that you need a recycler view without the recycling behavior, you could try viewHolder.setIsRecyclable(false); on every viewholder instantiation, that way they won't get recycled.
Set the below line in your activity
recyclerView.getRecycledViewPool().setMaxRecycledViews(1,0);
set Below Code in RecyclerViewAdapter class
#Override
public int getItemViewType(int position) {
return 1;
}
Related
I have a ListView with fairly tall and complex items but nothing too extreme. Each item is a CardView with a varying number of rows.
Unfortunately, it seems quite hard to make the scrolling completely smooth.
Even if the adapter's getView() method does pretty much nothing except returning the recycled view, there are frames above 16ms.
The slow frames have much slower draw times than other frames (such as 8ms) because the item is invalidated and drawn to cache when user scrolls to it (I assume).
I tried setting scrolling_cache to false, didn't help. Using a RecyclerView didn't improve the performance either.
First of all a ListView should not have a complex layout. If the ListView item can be expanded or something like that, there are other ways to do it. You might consider using ExpandableListView for this purpose.
But anyway, as your list item is a complex one, I ran through a similar situation earlier and I had to make the list item layout as simple as I could. I replaced all of my LinearLayout with RelativeLayout so that it reduces the View hierarchy.
If your list item (i.e. CardView) contains any image, you might have already considered using Glide or Picasso for loading the images.
Another trick I used once was to detect the fling scroll in the ListView using its onScrollListener for a complex list item.
#Override
public void onScrollStateChanged(AbsListView absListView, int scrollState) {
if(scrollState != SCROLL_STATE_FLING) {
// Populate views here
}
}
Avoid any database calls or loops inside your getView function. You might have considered them already. I'm just putting my thoughts altogether.
I have a for loop within a for loop within a for loop (3 for loops). Each for loop loads at least one view in them some load more than 1. All of the views(textviews, imageviews) are loaded into a relative layout or a linear layout and those layouts are all loaded into one linear layout and all of that is in a scrollview.
I know confusing and probably the worst way to do this. I have looked up different things most of them are listview related such as the endless adapter or lazy loading. I don't think listview will work for what i am trying to do. I have memory problems doing it this way.
So I guess what my question is will ListView be the right direction to go? Will i still be able to use my for-for-for loops?
Consider each block to represent a layout (each of layout consist of textviews, only the black boxes have imageviews and textviews) and also consider each color to represent a for loop. The black borders represent the linear layout that all of these views and other layouts get shoved into. Keep in mind it's not always going to be the same amount of black boxes beneath the red and blue boxes
i don't know if i really got what you want do here but in my opinion u should use an Adapter.
Doing this with layouts as you stated cause memory problems because you are loading a complex hierarchy of views, android is drawing all the views (even the ones that are not visible yet) and none of your views are reused.
Using a ListView and defining different types of AdapterView you should be able to do what you need.
For instance lets say each red box is one AdapterView. So from your scheme you'll have 2 AdapterView, lets call them "ViewOneBlueTwoBlack" and "ViewOneBlueThreeBlack". Also lets say you have more types of AdapterViews "ViewTwoBlueTwoBlack", "ViewTwoBlueFiveBlack", etc...
Now what you need to do is handle in your Adapter the conditions to know when each type of AdapterView should be load.
Or even better if you consider that the redboxes are sections and then the blue boxes become your AdapterViews.
You can find a nice tutorial on ListViews and Adapter here : http://www.vogella.com/tutorials/AndroidListView/article.html
Also your scheme looks a lot like a ExpandableListView check it out just in case.
You should definitly used a ListView and an adpater.
You can have diffenet view type in your ListView. To do so you should have an adapter like this :
public class YourAdapter extends BaseAdapter {
private static int HEADER_TYPE = 0;
private static int CONTENT_TYPE_1 = 1;
private static int CONTENT_TYPE_2 = 2;
#Override
public int getViewTypeCount() {
return 3;
}
#Override
public int getItemViewType(int position) {
if (header)
return HEADER_TYPE;
else if (content_type_1)
return CONTENT_TYPE_1;
else
return CONTENT_TYPE_2;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (getItemViewType(position) == HEADER_TYPE) {
//make header view
} else if (getItemViewType(position) == CONTENT_TYPE_1 {
//make content view
//be careful position is the position in the list view
} else {
//make content view
//be careful position is the position in the list view
return convertView;
}
}
You should be careful when accessing your datas in getView, the postion is the position in the ListView.
I would suggest you to use a table layout for this. Declare a table layout in your xml file, and add views dynamically.
I gave a similar answer here, you can customize the solution to have only one view in row and align accordingly.
"So I guess what my question is will ListView be the right direction to go? Will i still be able to use my for-for-for loops?"
Answer is, right direction depends upon your scenario if your objective can be achieved with both then see which method has least views or widgets in your case there are many layouts but if you use ListView there might be one. Bt in developing the best way is any way which fullfil customer's requirements..
I have decided to upgrade my code to use RecyclerView now instead of the list I am using now.
As I understand the following is how it normally goes:
onCreateViewHolder - this inflates a view, and does the findviewbyid and returns it as a ViewHolder object for the view
onBindViewHolder - this assigns the view holder values to the position view (which is being recycled).
This is all fine and dandy... If the views in the list contain the same fields...
My views however in my list are different, before I programmatically added views depending on the adapter List (in the getView method).
Is there a "good practice" way to handle this, I can't think of a good way to get around this.
getViewItemType does not work as the views are unique and that they are not predefined.
This is what you need to use when you different types of Views inside a ListView or RecyclerView :-
getItemViewType() and getViewTypeCount()
First you need to use getViewTypeCount() and return the number of unique views you need inside your List. Then override getItemViewType() and return the View type you want to inflate inside the List row.
Hope it will help.
If you still have any issue and need a working example, let me know, i'll update my answer.
I have a ListView in my app that is used to show a list with 2 types of items. The way it is currently implemented is that I have two different XML layouts for each of the item types, my adapter correctly reports the type and in the getView() method I inflate the appropriate XML according the the type in the specified position.
The problem is that in the vast majority of cases the structure of the list of items is that most of the type 1 items are in the beginning and most of the type 2 items are in the end, so usually at first you see mostly type 1 items, you scroll down and at some point you start seeing type 2 items, and they continue until the end of the list.
All works fine while I scroll until I hit that midpoint. Around that point all the calls to getView() get null passed as the convertView parameter. This makes sense obviously. The problem is that is seems like ListView stores all the previous type 1 views in the recycler, and I will not use them as long as I keep scrolling down since from now on most of the views will be type 2 views.
The views are pretty complex, with custom background and bitmaps on top of it, so I end up with lots of views in memory that I will probably never use.
My question is twofold:
Should I even worry about it? right now I am not in the point where I get OOM exceptions, but will I ever get there or is ListView smart enough to "let go" of some of those views when resources get tight?
If I do need to worry about it, is there a way to explicitly tell ListView to clear up it's recycler, or even disable it somehow?
A possible solution is to use the same XML for both layouts, have two ViewGroups in there and just set the visibility of one of them to GONE, but it seems like a waste to have a fairly complex view hierarchy if I am never going to show it.
Should I even worry about it?
No, as the user is perfectly capable of scrolling up, thereby returning to type 1 rows.
right now I am not in the point where I get OOM exceptions, but will I ever get there or is ListView smart enough to "let go" of some of those views when resources get tight?
Once you start getting OutOfMemoryError messages, this ListView will not be your problem. You only have so many row View structures, and all should be really cheap from a memory consumption standpoint.
One suggestion to deal with two different type of child view in Adapter is using getViewTypeCount method and let the adapter know actually you use two different type of view.
The listView maintains each recycler per each view type (in your case, the number will be 2), so you don't worry to any OOM exceptions and don't need to tell ListView to clear up it's recycler.
For more detailed description,
Check: getViewTypeCount and getItemViewType methods of ArrayAdapter
Code snippet for implementation:
public class SampleAdapter extends ArrayAdapter<String> {
...
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getItemViewType(int position) {
//the result must be in the range 0 to getViewTypeCount() - 1.
if( position < 10 )
return 0;
else
return 1;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
switch( getItemViewType(position) ){
case 0:
//do something for type1 view.
break;
case 1:
//do something for type2 view.
break;
}
return convertView;
}
}
I would not worry too much when having only 2 view types.
If you want to optimize it, I suggest not having a very complex layouts and instead use custom View and do drawing of the Bitmaps yourself. A bit more complex task, but will bring better UX when going through midpoint.
I was wondering how to show the snapshot of my notes, checklists, images in the grid view. I have no trouble creating the grid view but creating a preview of it is the challenge I'm facing right now as I need to add different type of views(text, checklist, imageview) to the grid according to their time of creation. Works fine for a single type of view like image or text only.
Or in other words. How do I add the different views dynamically to the GridView Adapter?
All or any help is appreciated.
Thanks.
They surely do not use a GridView for google Keep - but probably an Adapter nonetheless.
To use different Views with your Adapter you can use different View types:
Override getViewTypeCount() to return the number of View types you support.
Return the appropriate type in getItemViewType(int position) for this specific item.
Create the correct View in getView(int position, View convertView, ViewGroup parent).
Keep in mind that the rules for recycling, ViewHolder and so on still apply. For multiple types recycling only happens for the correct type.
Marcus Körner shared a gist by Jake Wharton on G+ recently that might be useful.
More than likely Google is using something similar to GridLayout, if not actually using a GridLayout.
Chances are the layout is also created programmatically to allow for the widgets to be different sizes based on the content that they each display.
Take a look at this recycle view with stagged
This manage make all what you need StaggeredGridLayoutManager
or look at this sorce Heterogenous Layouts inside RecyclerView
recyclerView= (RecyclerView) findViewById(R.id.recycler);
recyclerView.setLayoutManager(new
StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL));
initData();
MasonryAdapter adapter=new MasonryAdapter(productList);
recyclerView.setAdapter(adapter);
SpacesItemDecoration decoration=new SpacesItemDecoration(16);
recyclerView.addItemDecoration(decoration);