Reprint please indicate the source:
http://blog.csdn.net/zxt0601/article/details/53495709
This article is from: "Zhang Xudong's Blog" (http://blog.csdn.net/zxt0601)
Code Portal: If you like, point to a star. Thanks a lot
Https://github.com/mcxtzhang/SupportDemos
Background:
I'm going to write a series that explains the collection of useful tool classes that are commonly used or unpopular in Android support packages.
Recently leader was optimizing the list of IM sessions, and the previous practice of colleagues was to refresh Recyclerview without brain notifydatasetchanged ().
When the message is very hi, the interface refreshes frequently and the session list loses focus. And performance is not high after all.
You want to use directional refresh .
My colleague knew that I had studied diffutil and directed refresh related content, so I discussed with me.
(Don't know diffutil dot here) http://blog.csdn.net/zxt0601/article/details/52562770
(Do not know the point of directional refresh here) http://blog.csdn.net/zxt0601/article/details/52703280
Since the IM session list was read from the database, he also told me that there would be duplication of data sets , and that the list of sessions was definitely sorted by time , so this puts a two point requirement on our data organization: order, deduplication.
My idea is:
* Use Diffutil to automatically calculate the differences between old and new datasets, and then automatically complete the directed refresh .
* As for the weight and order of the data set, I intend to use TreeSet to help us do it.
The two requirements of the data organization are solved by using the feature of the set itself and the order of the tree .
But leader don't know where to find a SortedList, tell me this is provided by the Android SDK. You can also finish sorting and de-weight.
My heart said this is what road fairy, I thought it was the JDK, so also looked up some information, then opened the SortedList mystery, also has today's article.
Reprint please indicate the source:
http://blog.csdn.net/zxt0601/article/details/53495709
This article is from: "Zhang Xudong's Blog" (http://blog.csdn.net/zxt0601)
Code Portal: If you like, point to a star. Thanks a lot
Https://github.com/mcxtzhang/SupportDemos
What is SortedList?
The source pier notes are as follows:
A Sorted list implementation that can keep items in order and also notify for changes in the list.
Translation:
An implementation of a sequential list (dataset) that can keep itemdata in order and (auto) notification list (Recyclerview) changes in the (dataset).
Mutt
First it is a data structure, is an ordered list,list after the change (increase and remove), you can also keep the data set list orderly, and will automatically call **adapter in the direction of the update **notifyxxxx method, Update Recyclerview.
By the way, it will also automatically go heavy .
Key points:
With Recyclerview use, go heavy, orderly, auto-directed refresh
Just see here, I think this special auto-directed refresh this feature, how a bit like Diffutil, later I looked up the data only to find that this guy came out earlier than Diffutil, is in support Library 22 introduced. So that should be diffutil like it.
and SortedList and Diffutil have implemented and held a number of common interfaces, and the method name of the callback for us to rewrite the rules of comparison is almost a hair.
I personally feel sortedlist from the design and diffutil ratio, is a little bit inadequate, this may also be the official later in support Library 24 introduced diffutil a reason for it. Specific similarities and differences, summarized later. Let's see how to use it first.
Usage:
Let's take a look at how to write if you use SortedList:
Adapter:
To write Recyclerview, there is no adapter.
A regular adapter interior typically holds one List<T>
data set,
SortedList
If you use it, you need to change the variable type of the stored data source to SortedList.
* The only difference: Replace the previous arraylist-> with SortedList.
Other words, there is no change, because SortedList, although not inherited from the list, but the leak out of the API is the same as list.
Public class sortedadapter extends recyclerview. Adapter<sortedadapter. VH> { /** * Data source is replaced with SortedList, * ArrayList may have been used previously. */ PrivateSortedlist<testsortbean> Mdatas; ... public sortedadapter (Context mcontext, sortedlist<testsortbean> mdatas) { This. Mcontext = Mcontext; This. Mdatas = Mdatas; Minflater = Layoutinflater.from (Mcontext); } public void Setdatas (sortedlist<testsortbean> mdatas) { This. Mdatas = Mdatas; }@OverridePublic SORTEDADAPTER.VH Oncreateviewholder (viewgroup parent, int viewtype) {return NewSORTEDADAPTER.VH (Minflater.inflate (R.layout.item_diff, parent,false)); }@Overridepublic void Onbindviewholder (FinalSORTEDADAPTER.VH Holder,Finalint position) {Testsortbean Bean = mdatas.get (position); Holder.tv1.setText (Bean.getname ()); Holder.tv2.setText (Bean.getid () +""); Holder.iv.setImageResource (Bean.geticon ()); } ...}
Entity class
Without any modification, it is an ordinary entity class. The same as in diffutil above.
Callback:
Read Diffutil detailed classmate of this callback writing and understanding is easy, writing rules and routines and diffutil.callback the same.
And one less way to write, and here by the way, to public Object getChangePayload(int oldItemPosition, int newItemPosition)
review the above, this method returns a payload object that represents the changed content of the new and old item .
To say a little farther here, the less-written method is the core method of partial bind (partial bind) in directed refreshes.
DiffUtil
is to use the getChangePayload()
return value of this method, as the third parameter, ListUpdateCallback
the callback interface void onChanged(int position, int count, Object payload);
method, the final callback adapter.notifyItemRangeChanged(position, count, payload);
method, and then go down to the adapter three-parameter method, that is, onBindViewHolder(VH holder, int position, List<Object> payloads)
we partially bound the operation of the place, Not very clear can go to see Diffutil detailed.
In addition, the new and old data sets come in, and each of these methods is directly passed into the ItemData for comparison.
Then our SortedList callback is written as follows:
Public class sortedlistcallback extends sortedlistadaptercallback< Testsortbean> {Public Sortedlistcallback (Recyclerview.adapter Adapter) {Super(adapter); }/** * Think of it as equals method. @Overridepublic int Compare (Testsortbean O1, Testsortbean O2) {returnO1.getid ()-O2.getid (); }The /** * is consistent with the Diffutil method to determine whether two objects are the same item. */ @Overridepublic boolean areitemsthesame (Testsortbean item1, Testsortbean item2) {returnItem1.getid () = = Item2.getid (); }/** * and Diffutil methods are consistent, returning false, representing the item content change. Will callback the mcallback.onchanged () method; */ @Overridepublic boolean arecontentsthesame (Testsortbean olditem, Testsortbean newitem) {//default same as a different one is different if(Olditem.getid ()! = Newitem.getid ()) {return false; }if(Olditem.getname (). Equals (Newitem.getname ())) {return false; }if(Olditem.geticon ()! = Newitem.geticon ()) {return false; }return true; }}
Activity:
The writing of activity has not changed much, the difference is as follows:
* When building adapter, the data is usually passed together and can now be transmitted.
* When initializing the SortedList, the adapter will be passed in. So build adapter first, then build SortedList
Public class sortedlistactivity extends appcompatactivity { /** * Data source is replaced with SortedList, * ArrayList may have been used previously. */ PrivateSortedlist<testsortbean> Mdatas;PrivateRecyclerview MRv;PrivateSortedadapter Madapter;@Override protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate); Setcontentview (r.layout.activity_sorted_list); MRv = (Recyclerview) Findviewbyid (R.ID.RV); Mrv.setlayoutmanager (NewLinearlayoutmanager ( This));//★ used to build adapter, the data is usually passed together, and now there are changesMadapter =NewSortedadapter ( This,NULL); Mrv.setadapter (Madapter); InitData (); Madapter.setdatas (Mdatas); }Private void InitData() {when//★sortedlist is initialized, the adapter is passed in. So build adapter first, then build SortedListMdatas =NewSortedlist<> (Testsortbean.class,NewSortedlistcallback (Madapter)); Mdatas.add (NewTestsortbean (Ten,"Android", R.drawable.pic1));//★ Note here that there is a repeating field that will automatically go heavy. Mdatas.add (NewTestsortbean (Ten,"Android Repeat", R.drawable.pic1)); Mdatas.add (NewTestsortbean (2,"Java", R.drawable.pic2)); Mdatas.add (NewTestsortbean ( -,"Back pot", R.DRAWABLE.PIC3)); Mdatas.add (NewTestsortbean (4,"Hand torn Products", R.DRAWABLE.PIC4)); Mdatas.add (NewTestsortbean ( -,"Hand tear Test", R.DRAWABLE.PIC5)); }
The code is written here, and the interface can be displayed normally. Effects such as GIF graphs.
We can see that although the data we add is repetitive, the order is chaotic.
But the list interface is still displayed in ascending order of ID.
Is this the end of the thing, not to mention auto-directed refresh?
0-Step Auto-directed refresh
and diffutil two steps to complete the directional refresh ratio, SortedList this is really strong. 0 Steps to complete auto-directed refresh .
Add a new article:
On the basis of the above code, if you query the database at this time to find a new IM chat information, then the direct Add ()
come in:
Add internal automatically calls mcallback.oninserted (index , 1)
-> notifyitemrangeinserted (index,1)
That is, we add it once notify once, no batch operation, a little low
mDatas.add(new TestSortBean(26"温油对待产品", R.drawable.pic6));//模拟新增 mDatas.add(new TestSortBean(12"小马可以来点赞了", R.drawable.pic6));//模拟新增 mDatas.add(new TestSortBean(2"Python", R.drawable.pic6));//add进去 重复的会自动修改
Add a lump:
If it is a piece of news, you can use addAll()
, view the source code, it will automatically do batch operations, beginBatchedUpdates();
and endBatchedUpdates();
. So if you want to batch, you have to use the AddAll () operation, feeling that this is a limit.
AddAll is divided into two types//first with variable parameters AddAll//mdatas. AddAll(New Testsortbean ( -,"Good"+ U. drawable. pic6), New Testsortbean ( -,"Good"+ U. drawable. pic6));Second Set form list<testsortbean> temp = new arraylist<> ();Temp. Add(New Testsortbean ( -,"Good"+ U. drawable. pic6));Temp. Add(New Testsortbean ( -,"Good"+ U. drawable. pic6));Mdatas. AddAll(temp);
Refresh
And if it is the scene of the refresh, it may not be applicable, when refreshed, the server gives us a list of the general, direct addall to clear, will splash screen:
list<testsortbean> Newdatas = new Arraylist<> ();for (int i =0; i < mdatas.size (); i++) {try {Newdatas. Add(Mdatas. Get(i). Clone());//clone the old data, simulate the refresh operation} catch (Clonenotsupportedexception e) {E. Printstacktrace();}} Newdatas. Add(New Testsortbean ( in,"Good"+ U. drawable. pic6));//Simulate new dataNewdatas. Get(0). SetName("android+");Newdatas. Get(0). SetIcon(R. drawable. pic7);//Simulate modifying dataTestsortbean Testbean = Newdatas. Get(1);//Analog Data displacementNewdatas. Remove(Testbean);Newdatas. Add(Testbean);Mdatas. Clear();Mdatas. AddAll(Newdatas);
Asynchronous operation
View the source code, SortedList is in each add()
,,, ... etc. in the function of the addAll()
clear()
data set to be added and censored, it will be sorted and de-weighed again. This sort and de-weight is obviously a time-consuming operation. So I'm going to say can I use asynchronous processing? Dropped in the child thread.
So I write as follows:
//each add is calculated once to be placed in a child thread new Thread (new Runnable () { @Override public void Span class= "Hljs-title" >run () {Mdatas.add (new Testsortbean (26 , "handsome" , r.drawable.pic6)); //simulation new data Mdatas.add (new Testsortbean (27 , "handsome" , r.drawable.pic6)); //simulation new Data } }). Start (); }
However, this is certainly not possible, as mentioned above, each add will automatically madapter.notifyitemrangeinserted (position, count);
Manipulating the UI in a thread will android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
This is better than diffutil.
Similarities and differences between Diffutil and the
They are both really alike, and the callback interfaces that are held internally are the same, whether after the diff is computed or after the data has been DiffUtil
SortedList
modified: android.support.v7.util.ListUpdateCallback
/** * An interface the can receive Update operations that is applied to a list. * <p> * This class can be used Together with Diffutil to detect changes between and lists. */ Public interface listupdatecallback { voidOninserted (intPositionintcount);voidOnremoved (intPositionintcount);voidOnmoved (intFromposition,intToposition);voidOnChanged (intPositionintCount, Object payload);}
I will not parse the source code, very simple, the general process is:
DiffUtil
After calculating Diff
or SortedList
realizing that the data set has changed, in the appropriate time, the callback ListUpdateCallback
interface of the four methods, DiffUtil
and SortedList
the provided default callback implementation, will notify adapter to complete the directed refresh.
This is the principle of auto-directed refresh .
Let's summarize their similarities and differences :
* Diffutil compares the difference (diff) of two data sources (typically list), and the parameters passed in callback are position
* SortedList can complete the sorting and de- weight of the data set, callback in the comparison, the ItemData (JavaBean) is passed.
* Diffutil can complete auto-directed refresh + Partial binding
* SortedList can only complete auto-directed refresh
* Diffutil is more general, SortedList is also coupled with data structure
* Diffutils: The detection of duplicates is considered to be new. (Because the core of the comparison is postion.) So I can not go to heavy) but im this message sequence movement will be detected.
* They are all a means of automatic orientation refresh
Experience Summary:
With SortedList, the variable type of the adapter save DataSet is changed.
The code is intrusive and does not have hot-swappable pleasure.
Under the premise of various baseadapter in the project, it is possible to extend a basesortedlistadater more conveniently.
But it is not intended to be a directed refresh, but to maintain the order & deduplication of the data set.
With a directional refresh feature.
and Diffutil main is to compare sets of differences , but also help us to automatically complete the directional refresh .
So SortedList does not apply to all data sent by the server, drop-down refresh situation. It's better to use a normal list at this point.
Its highlights and core, or is in order & to Weight .
And it also does not support partial binding (partial bind).
Reprint please indicate the source:
http://blog.csdn.net/zxt0601/article/details/53495709
This article is from: "Zhang Xudong's Blog" (http://blog.csdn.net/zxt0601)
Code Portal: If you like, point to a star. Thanks a lot
Https://github.com/mcxtzhang/SupportDemos
"Android" You may not know the support (a) 0-step Auto-directed refresh: SortedList