PS: I feel these two methods are actually very easy to understand, but also to my other two friends write it, help them understand the use of these two methods and concepts. At the same time, there are some minor details to be aware of.
Learning content:
1.getItemViewType and Getviewtypecount
Getitemviewtype and Getviewtypecount are the two related methods for implementing a complex list in a ListView, and the item in the normal ListView is the same, so we only need to implement the four abstract methods in the adapter, But what if the item on the page is more complex? For example, this.
For example, this list item, in fact, is not very complex, this type of item also has other implementations, such as the implementation of Sectionindexer in adapter can also be achieved, but we take this to illustrate the problem, If the first type of item is TextView and the second type is imageview+button+textview, then we need to use Getitemviewtype () and Gettypeviewcount () for such a complex list. Two ways to achieve it. These two methods are easier to understand, getting the type of the item and the associated number of type in item. Nonsense is not much to say, directly say the way to achieve.
PublicClass ListAdapterExtendsBaseadapter {/*** Item type, int value. Must be incremented starting from 0. **/PrivateStaticFinalint type_title = 0;PrivateStaticFinalint type_content = 1;/*** Number of Item Type **/PrivateStaticFinalint type_item_count = 2;/**Data*/Private list<company> Mdata =New arraylist<>();PrivateContext context;Public ListAdapter (Context context,list<company>Mdata) {This.context =ContextThis.mdata =Mdata; } @OverridePublicIntGetCount () {ReturnMdata.size (); } @OverridePublic Object GetItem (IntPosition) {ReturnMdata.get (position); } @OverridePublicLong Getitemid (IntPosition) {ReturnPosition } @OverridePublic View GetView (IntPosition, View Convertview, ViewGroup viewgroup) {/*** Different Types of Viewholder **/Titleviewholder Titleviewholder =Null; Companyviewholder Contentviewholder =Null;/*** To judge the type, inflate the different layouts separately. **/Switch(Getitemviewtype (position)) {CaseType_title:titleviewholder =NewTitleviewholder ();if (Convertview = =Null) {Convertview = View.inflate (context, R.layout.view_holder_company_index,Null); Titleviewholder.title =(TextView) Convertview.findviewbyid (r.id.tv_title);//Settag ()Convertview.settag (Titleviewholder); }Else{//Gettag (); Titleviewholder =(Titleviewholder) Convertview.gettag (); } titleViewHolder.title.setText (Mdata.get (position). GetName ());Break;CaseType_content:contentviewholder =NewCompanyviewholder ();if (Convertview = =Null) {Convertview = View.inflate (Context,r.layout.view_holder_company,Null); Contentviewholder.content =(TextView) Convertview.findviewbyid (r.id.tv_content); Convertview.settag (Contentviewholder); }Else{Contentviewholder =(Companyviewholder) Convertview.gettag (); } contentViewHolder.content.setText (Mdata.get (position). GetCode ());Break; }ReturnConvertview; }/*** Get the type of item according to position **/@OverridePublicint Getitemviewtype (IntPosition) {If(Textutils.isempty (Mdata.get (position). GetCode ())) {Return Type_title;} else{return Type_content; }} /** * Returns the total number of item type * */ @Override public Span style= "color: #0000ff;" >int Getviewtypecount () {return Type_item_count; } static classstatic class
- First we need to set a different value, int value for different item, because Getitemviewtype returns an int value, so it needs to be defined as an int, which must start at 0 and increment sequentially. The reason I follow will explain.
- Overriding the Getitemviewtype and Getviewtypecount methods, Getviewtypecount returns the total type of item, and Getviewtypecount needs to be judged, Judging methods are generally judged by the relevant fields in the JavaBean, so this piece does not need to be too tangled. Just make a judgment based on the specific type of item that position gets and then return to it.
- Define Viewholder to define multiple viewholder and reduce the number of Findviewbyid () depending on the type of different needs.
- Rewrite the related method in GetView (), in GetView first to get the type of item according to position to load the unused layout, here also setviewtype for different types of item set RecycleBin, Resolves a listview because of multiple types of item reuse issues. It is not clear that the reader of the recyclebin mechanism can look at the reuse mechanism of the ListView. Here we talk about RecycleBin, if you do not understand the mechanism is not understand the following explanation.
- Finally, according to the data passed Setadapter then the item is assigned to complete.
A general idea is to do this, and here's why it's necessary to start with the type of item you want from 0, and then increment it, so what's the reason for that? If we have three types, we will define the item as 1,2,4, then there is bound to appear arrayindexoutofboundsexception, that is, the so-called array out of bounds, I went online to check a lot of information is said to be abnormal, and Google has indeed marked, Note:integers must is in the range 0 getViewTypeCount()
to-1. IGNORE_ITEM_VIEW_TYPE
can also is returned. But there is no follow-up, no one will explain how this problem happened, why to define it. Maybe I'm the kind of person who has a busy egg and doesn't really feel uncomfortable. I'm explaining the specific reasons:
In fact, this is usually the case when we pull down the problem, when the first load of the first page will not be directly collapsed, then cautious readers may understand that this may be the ListView in the back of the problem, in fact, is the ListView reuse mechanism caused. Let's take a look at this method:
/***listview This method is called when it is reused for different item * Set a recyclebin for each different item for reuse.*/Publicvoid Setviewtypecount (IntViewtypecount) {if (Viewtypecount < 1) {ThrowNew IllegalArgumentException ("Can ' t has a Viewtypecount < 1"); }//Noinspection unchecked/*** Set a ArrayList based on the number of Viewtypecount. * Also set a ArrayList for each item to store the Scrapview. * Equivalent to a two-dimensional array to maintain the Scrapview array for each item. * This is the equivalent of setting a separate recyclebin for different item.*/ arraylist<view>[] Scrapviews = new Arraylist[viewtypecount]; for (int i = 0; i < viewtypecount; I++new arraylist<view> ();} // save Viewtypecount, also = 2 mviewtypecount =// The current scrap is the Scrapview array of the first item. Mcurrentscrap = Scrapviews[0//mscrapviews saves a two-dimensional array maintained recyclebin. Mscrapviews =< Span style= "color: #000000;" > Scrapviews;}
This is the specific data structure, the simple understanding is that each item has a corresponding Scrapview array. This is not really a problem here, we all know that once the item is removed from the screen, the first will be detach off, and then added to the Mscrapview array (discard view pool), then in the Addscrapview when the exception occurs.
voidAddscrapview (View scrap) {Abslistview.layoutparams LP =(abslistview.layoutparams) scrap.getlayoutparams ();if (LP = =Null) {Return; }//Don ' t put the header or footer views or views of the should be ignored//Into the scrap heapint ViewType =Lp.viewtype;if (!Shouldrecycleviewtype (ViewType)) {if (ViewType! = Item_view_type_header_or_footer) {Removedetachedview (scrap, falsereturn/** * The core code is this piece, because we mviewtypecount! = 1, so the IF condition is not established. * Therefore, the else code is executed. */if (Mviewtypecount = = 1 elseif (Mrecyclerlistener! = null
The problem is that in This else code, we can see that the Mscrapviews[viewtype].add (scrap) code executes, as shown in the previous picture, that mscrapviews[] is the kind of number new that is based on item. , since our item totals are two types, then Mscrapviews[].length = 2, but here is what Mscrapview[viewtype],viewtype is, in fact, the return value of our getitemviewtype, If we define the type as 2 and 3, then he will visit mscrapview[2] and mscrapview[3], it is conceivable that there will be arrayindexoutoffboundsexception. This is the real reason why the array is out of bounds.
The basic explanation is over, paste a source from github: Demo download
Android's ListView Getitemviewtype and Getviewtypecount