In the previous article  RecyclerView Source code analysis ( One ) —— Drawing process analysis   It introduces  RecyclerView Drawing process of ,RecyclerView By drawing the flow from View Out of it , Put it in LayoutManager in , bring  RecyclerView In different  LayoutManager in , Have different styles , bring RecyclerView remarkable dexterity , Greatly enhanced  RecyclerView Use scenarios .

Of course ,RecyclerView One of its unique advantages is its caching mechanism , It reduces the memory consumption and repeated drawing work , therefore , This article is intended to introduce and learn  RecyclerView The idea of cache design based on .

When we're talking about mixed storage , It's going to go through creating - cache - The process of reuse . So for  RecyclerView The caching mechanism is also carried out according to the following steps .

establish  ViewHolder(VH)

When it comes to pairs itemView When measuring ,layoutChunk In the method, we get each one first itemView, After obtaining , Add it to  RecyclerView in . So let's first look at the creation process :

        View next(RecyclerView.Recycler recycler) {
if (mScrapList != null) {
return nextViewFromScrapList();
final View view = recycler.getViewForPosition(mCurrentPosition);
mCurrentPosition += mItemDirection;
return view;

next  It's called  RecyclerView  Of  getViewForPosition  Method to get a  View  Of . and  getViewForPosition  Method will eventually call  RecyclerView  Of tryGetViewHolderForPositionByDeadline  Method .


It's a long way , But the logic is simple , The first part of the whole process is to try to get from the cache VH, If you can't find it , Will create new VH, Then bind the data , In the end, it will be VH Bound to the  LayoutParams (LP) On .

        ViewHolder tryGetViewHolderForPositionByDeadline(int position,
boolean dryRun, long deadlineNs) {
if (position < 0 || position >= mState.getItemCount()) {
throw new IndexOutOfBoundsException("Invalid item position " + position
+ "(" + position + "). Item count:" + mState.getItemCount()
+ exceptionLabel());
boolean fromScrapOrHiddenOrCache = false;
ViewHolder holder = null;
// Omit lookup from cache VH The logic of , Here's what happens if you still don't find it , I'm going to create a new one if (holder == null) {
long start = getNanoTime();
if (deadlineNs != FOREVER_NS
&& !mRecyclerPool.willCreateInTime(type, start, deadlineNs)) {
// abort - we have a deadline we can't meet
return null;
            // establish VH
holder = mAdapter.createViewHolder(RecyclerView.this, type);
// only bother finding nested RV if prefetching
RecyclerView innerView = findNestedRecyclerView(holder.itemView);
if (innerView != null) {
holder.mNestedRecyclerView = new WeakReference<>(innerView);
} long end = getNanoTime();
mRecyclerPool.factorInCreateTime(type, end - start);
if (DEBUG) {
Log.d(TAG, "tryGetViewHolderForPositionByDeadline created new ViewHolder");
} // This is very ugly but the only place we can grab this information
// before the View is rebound and returned to the LayoutManager for post layout ops.
// We don't need this in pre-layout since the VH is not updated by the LM.
if (fromScrapOrHiddenOrCache && !mState.isPreLayout() && holder
.hasAnyOfTheFlags(ViewHolder.FLAG_BOUNCED_FROM_HIDDEN_LIST)) {
holder.setFlags(0, ViewHolder.FLAG_BOUNCED_FROM_HIDDEN_LIST);
if (mState.mRunSimpleAnimations) {
int changeFlags = ItemAnimator
changeFlags |= ItemAnimator.FLAG_APPEARED_IN_PRE_LAYOUT;
final ItemHolderInfo info = mItemAnimator.recordPreLayoutInformation(mState,
holder, changeFlags, holder.getUnmodifiedPayloads());
recordAnimationInfoIfBouncedHiddenView(holder, info);
} boolean bound = false;
if (mState.isPreLayout() && holder.isBound()) {
// do not update unless we absolutely have to.
holder.mPreLayoutPosition = position;
} else if (!holder.isBound() || holder.needsUpdate() || holder.isInvalid()) {
if (DEBUG && holder.isRemoved()) {
throw new IllegalStateException("Removed holder should be bound and it should"
+ " come here only in pre-layout. Holder: " + holder
+ exceptionLabel());
final int offsetPosition = mAdapterHelper.findPositionOffset(position);
          // Data binding
bound = tryBindViewHolderByDeadline(holder, offsetPosition, position, deadlineNs);
} final ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
final LayoutParams rvLayoutParams;
       // The following logic is to VH Bound to the LP, LP It's set to ItemView On
if (lp == null) {
rvLayoutParams = (LayoutParams) generateDefaultLayoutParams();
} else if (!checkLayoutParams(lp)) {
rvLayoutParams = (LayoutParams) generateLayoutParams(lp);
} else {
rvLayoutParams = (LayoutParams) lp;
rvLayoutParams.mViewHolder = holder;
rvLayoutParams.mPendingInvalidate = fromScrapOrHiddenOrCache && bound;
return holder;

Even if you omit the middle lookup from the cache VH The logic of , The rest of the code is still very long . Let me recapitulate  tryGetViewHolderForPositionByDeadline What method does :

  1. Look up from the cache VH ;

  2. The cache does not , Then create a VH;

  3. Judge VH Need to update data , If necessary, it will call  tryBindViewHolderByDeadline Data binding ;

  4. take VH Bound to the LP, LP It's set to ItemView On , Depend on each other ;

Here's about creating VH That's the end of the logic .


In introducing the logic added to the cache , Still need to introduce cache related classes and variables .

Cache overall design

It can be seen from the picture that ,RecyclerView Cache is a four level cache architecture . Of course , from RecyclerView From the comments on the code , Officially, there's only three levels of cache , namely mCachedViews It's the first level cache ,mViewCacheExtension It's L2 cache ,mRecyclerPool Is L3 cache . From a developer's point of view ,mAttachedScrap and mChangedScrap It's not transparent to developers , Officials have not revealed any way to change their behavior .

Caching mechanisms Recycler Detailed explanation

Recycler yes RecyclerView An inner class . Let's take a look at its main member variables .

  • mAttachedScrap Cache the visible range of ViewHolder

    final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>();

  • mChangedScrap  When the cache is sliding, it will be connected with RecyclerView The separation of ViewHolder, Click View Of position or id cache , By default, it can store at most 2 individual

    ArrayList<ViewHolder> mChangedScrap = null;

  • mCachedViews  ViewHolder Cache list , Its size is determined by mViewCacheMax decision , Default DEFAULT_CACHE_SIZE by 2, It can be set dynamically .

    final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>();

  • ViewCacheExtension  A layer of cache that developers can customize , It's a virtual class ViewCacheExtension An example of , Developers can implement methods getViewForPositionAndType(Recycler recycler, int position, int type) To implement your own cache .

    private ViewCacheExtension mViewCacheExtension;

  • RecycledViewPool ViewHolder Buffer pool , In the Limited mCachedViews If you can't save it ViewHolder when , It will ViewHolder Deposit in RecyclerViewPool in .

    RecycledViewPool mRecyclerPool;

Add to cache

VH After being created , Is to be cached , And then recycled , So when were they added to the cache ? This is still based on LinearLayoutManager Illustrate with examples . stay  RecyclerView Source code analysis ( One ) —— Drawing process analysis   A method was mentioned in the article :

 public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
     // ...
     // ...

onLayoutChildren It's right view Drawing . In pairs view Will call first  detachAndScrapAttachedViews Method , Let's take a look at this method .


Let's take a look at this method :

       // recyclerview
public void detachAndScrapAttachedViews(@NonNull Recycler recycler) {
final int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
final View v = getChildAt(i);
          // Every view It's going to be in there
scrapOrRecycleView(recycler, i, v);
} private void scrapOrRecycleView(Recycler recycler, int index, View view) {
final ViewHolder viewHolder = getChildViewHolderInt(view);
if (viewHolder.shouldIgnore()) {
if (DEBUG) {
Log.d(TAG, "ignoring view " + viewHolder);
        // If VH Invalid , And it has been removed , It's going to be another logic
if (viewHolder.isInvalid() && !viewHolder.isRemoved()
&& !mRecyclerView.mAdapter.hasStableIds()) {
} else {
          // First detch fall , And then put it in the cache

In the logic above , Put in the cache . You can see it here

  1. If it is remove, Will execute  recycleViewHolderInternal(viewHolder)  Method , And this approach will eventually ViewHolder Join in CacheView and Pool in ,

  2. And when it's Detach, Will View Add to ScrapViews in

One thing to point out is : Two concepts need to be distinguished ,Detach  and  Remove

  1. detach: stay ViewGroup The implementation in is simple , Just to ChildView from ParentView Of ChildView Remove from array ,ChildView Of mParent Set to null, It can be understood as lightweight temporary remove, because View At this point and View The tree is still broken , This function is often used to change ChildView stay ChildView The order in the array .View By detach It's usually temporary , It's going to be rebuilt later attach.

  2. remove: Real removal , It's not just from ChildView Remove names from arrays , Others and View The tree's connections will be cut off ( Don't consider Animation/LayoutTransition This special situation ), For example, the focus is cleared , from TouchTarget And so on .


The following term Recycler  Two specific logical methods :

* internal implementation checks if view is scrapped or attached and throws an exception
* if so.
* Public version un-scraps before calling recycle.
void recycleViewHolderInternal(ViewHolder holder) {
       // ... Omit the previous code , The front is doing the test
final boolean transientStatePreventsRecycling = holder
final boolean forceRecycle = mAdapter != null
&& transientStatePreventsRecycling
&& mAdapter.onFailedToRecycleView(holder);
boolean cached = false;
boolean recycled = false;
if (DEBUG && mCachedViews.contains(holder)) {
throw new IllegalArgumentException("cached view received recycle internal? "
+ holder + exceptionLabel());
if (forceRecycle || holder.isRecyclable()) {
if (mViewCacheMax > 0
&& !holder.hasAnyOfTheFlags(ViewHolder.FLAG_INVALID
| ViewHolder.FLAG_UPDATE
// Retire oldest cached view If the number of caches exceeds , The first one will be removed
int cachedViewSize = mCachedViews.size();
if (cachedViewSize >= mViewCacheMax && cachedViewSize > 0) {
} int targetCacheIndex = cachedViewSize;
&& cachedViewSize > 0
&& !mPrefetchRegistry.lastPrefetchIncludedPosition(holder.mPosition)) {
// when adding the view, skip past most recently prefetched views
int cacheIndex = cachedViewSize - 1;
while (cacheIndex >= 0) {
int cachedPos = mCachedViews.get(cacheIndex).mPosition;
if (!mPrefetchRegistry.lastPrefetchIncludedPosition(cachedPos)) {
targetCacheIndex = cacheIndex + 1;
            // Add to cache
mCachedViews.add(targetCacheIndex, holder);
cached = true;
if (!cached) {
addViewHolderToRecycledViewPool(holder, true);
recycled = true;
} else { }
// even if the holder is not removed, we still call this method so that it is removed
// from view holder lists.
if (!cached && !recycled && transientStatePreventsRecycling) {
holder.mOwnerRecyclerView = null;

What this method does is as follows :

  1. Test the VH The effectiveness of the , Make sure it's no longer used ;

  2. Determine the capacity of the cache , If it exceeds the limit, it will be removed , Then find a suitable place to add .

  3. If you can't join CacheViews in , Then add to Pool in .


mCachedViews The corresponding data structure is also ArrayList But the cache is limited to the size of the collection , The default is 2. In this cache ViewHolder Characteristics and mAttachedScrap The features in are the same , as long as position perhaps itemId Corresponding to the , So it's clean , No need to rebind data . Developers can call setItemViewCacheSize(size) Method to change the size of the cache . A common scenario triggered by this level of caching is sliding RV. Of course notifyXXX The cache is also triggered . The cache and mAttachedScrap It's also very efficient .


RecyclerViewPool Caching can be for multiple ItemType, Set cache size . The default for each ItemType The number of caches is 5. And the cache can be used for multiple users RecyclerView share . Because the default number of caches is 5, Suppose there's a news App, Every screen can show 10 News , Then it will inevitably lead to cache hit failure , Frequent results in the creation of ViewHolder Affect performance . So you need to expand the cache size.


Next look  scrapView This method :

        void scrapView(View view) {
final ViewHolder holder = getChildViewHolderInt(view);
if (holder.hasAnyOfTheFlags(ViewHolder.FLAG_REMOVED | ViewHolder.FLAG_INVALID)
|| !holder.isUpdated() || canReuseUpdatedViewHolder(holder)) {
if (holder.isInvalid() && !holder.isRemoved() && !mAdapter.hasStableIds()) {
throw new IllegalArgumentException("Called scrap view with an invalid view."
+ " Invalid views cannot be reused from scrap, they should rebound from"
+ " recycler pool." + exceptionLabel());
holder.setScrapContainer(this, false); // there false
} else {
if (mChangedScrap == null) {
mChangedScrap = new ArrayList<ViewHolder>();
holder.setScrapContainer(this, true); // Here is true

This method is relatively simple , There's not so much logic to test . Here, according to the conditions , There are two cache types to choose from , It's not going to be specific , You can understand it . Here are two  scrapView The cache of .


mAttachedScrap The corresponding data structure of is ArrayList, stay LayoutManager#onLayoutChildren In the method , Yes views When doing layout , Will RecyclerView Upper Views Save all to this collection , For future use , In this cache ViewHolder Its characteristic is , If and RV Upper position perhaps itemId Match up , So think it's clean ViewHolder, It can be used directly , Don't need to call onBindViewHolder Method . The ArrayList There is no limit to the size of , How many on the screen View, How large a collection will be created .

The scenario that triggers this level of caching is to call notifyItemXXX Method . call notifyDataSetChanged Method , Only when Adapter hasStableIds return true, Will trigger cache usage at that level .


mChangedScrap and mAttachedScrap It's the same level of caching , They are equal . however mChangedScrap The call scenario for is notifyItemChanged and notifyItemRangeChanged, Only those that have changed ViewHolder Will be put into mChangedScrap in .mChangedScrap In the cache ViewHolder Yes, you need to call onBindViewHolder Method to rebind the data . Then there is a problem , Why do two different caches need to be designed for the same level of cache ?

stay dispatchLayoutStep2 Stage LayoutManager onLayoutChildren Method will eventually call layoutForPredictiveAnimations Method , hold mAttachedScrap In the rest of the ViewHolder Fill in the screen , So the difference between them is ,mChangedScrap Medium ViewHolder stay RV When it's full , It will not be forced to fill in RV Upper . So there's a way to make things change ViewHolder Get into mAttachedScrap Cache ? Certainly. . call notifyItemChanged(int position, Object payload) Methods can be , Realize local refresh function ,payload Not empty , So what's changed ViewHolder It's going to be separated into mAttachedScrap Medium .

Use the cache

Let's move on to the last section , Use the cache . This is also mentioned in the previous section , Let's take a look at the corresponding method :

// Based on the incoming position obtain ViewHolder
ViewHolder tryGetViewHolderForPositionByDeadline(int position,
boolean dryRun, long deadlineNs) {
--------- Omit ----------
boolean fromScrapOrHiddenOrCache = false;
ViewHolder holder = null;
// Pre layout It's a special case from mChangedScrap In order to get ViewHolder
if (mState.isPreLayout()) {
holder = getChangedScrapViewForPosition(position);
fromScrapOrHiddenOrCache = holder != null;
if (holder == null) {
//1、 Try from mAttachedScrap In order to get ViewHolder, At this time, we get the... In the visible range of the screen ViewHolder
//2、mAttachedScrap If not in the cache , Continue from mCachedViews Try to get ViewHolder
holder = getScrapOrHiddenOrCachedHolderForPosition(position, dryRun);
---------- Omit ----------
if (holder == null) {
final int offsetPosition = mAdapterHelper.findPositionOffset(position);
--------- Omit ----------
final int type = mAdapter.getItemViewType(offsetPosition);
// If Adapter The statement is made. Id, Try from id In order to get , This is not a cache
if (mAdapter.hasStableIds()) {
holder = getScrapOrCachedViewForId(mAdapter.getItemId(offsetPosition),
type, dryRun);
if (holder == null && mViewCacheExtension != null) {
3、 From the custom cache mViewCacheExtension Trying to get ViewHolder, This cache needs to be implemented by developers
final View view = mViewCacheExtension
.getViewForPositionAndType(this, position, type);
if (view != null) {
holder = getChildViewHolder(view);
if (holder == null) { // fallback to pool
//4、 From the cache pool mRecyclerPool Trying to get ViewHolder
holder = getRecycledViewPool().getRecycledView(type);
if (holder != null) {
// If successful , Reset ViewHolder state , So it needs to be re executed Adapter#onBindViewHolder Data binding
if (holder == null) {
--------- Omit ----------
//5、 If none of the above is found in the cache ViewHolder, Will eventually call Adapter Medium onCreateViewHolder Create a
holder = mAdapter.createViewHolder(RecyclerView.this, type);
} boolean bound = false;
if (mState.isPreLayout() && holder.isBound()) {
holder.mPreLayoutPosition = position;
} else if (!holder.isBound() || holder.needsUpdate() || holder.isInvalid()) {
final int offsetPosition = mAdapterHelper.findPositionOffset(position);
//6、 If you need to bind data , Would call Adapter#onBindViewHolder To bind data
bound = tryBindViewHolderByDeadline(holder, offsetPosition, position, deadlineNs);
---------- Omit ----------
return holder;

The above logic is represented by a flow chart :

Summarize the above process : adopt mAttachedScrap、mCachedViews And mViewCacheExtension Acquired ViewHolder No need to recreate layout and bind data ; Through the cache pool mRecyclerPool Acquired ViewHolder No need to recreate the layout , But you need to rebind the data ; If there is no target in the above cache ViewHolder, Then it will be called back Adapter#onCreateViewHolder Create a layout , And callback Adapter#onBindViewHolder To bind data .


We already know ViewCacheExtension Belongs to the third level cache , It needs to be implemented by developers themselves , that ViewCacheExtension In what scenarios ? How did it come true ?

First of all, we need to be clear about , That's it  Recycler  It has set up several levels of cache , Why leave an interface for developers to implement caching on their own ?

On this point , Let's see  Recycler  Other caches in :

  1. mAttachedScrap  The cache used to handle the visible screen ;

  2. mCachedViews  The data stored in is based on  position  Caching , But the data in it may be replaced at any time ;

  3. mRecyclerPool  Li press  viewType  De storage  ArrayList< ViewHolder>, therefore  mRecyclerPool  Do not press the  position  De storage  ViewHolder, And from  mRecyclerPool  Take out  View  I have to go every time  Adapter#onBindViewHolder  To rebind the data .

If I need to be in a specific position right now ( such as position=0 Location ) Always show someone View, And the content is unchanged , Well, the best thing to do is to be in a particular position , There's no need to recreate every time View, You don't have to rebind the data every time , The above caches are obviously not applicable , What should we do in this situation ? You can customize the cache  ViewCacheExtension  To achieve the above .

RecyclerView & ListView Cache mechanism comparison

The conclusion is quoted from :Android ListView And RecyclerView Comparative analysis -- Caching mechanisms

ListView and RecyclerView The caching mechanism is basically the same :

  1. mActiveViews and mAttachedScrap Functions are similar , The point is to quickly reuse the list items visible on the screen ItemView, And there's no need to re createView and bindView;

  2. mScrapView and mCachedViews + mReyclerViewPool Functions are similar , The point is to cache what's off the screen ItemView, The goal is to get the ItemView reusing .

  3. RecyclerView The advantage is that

    1. mCacheViews Use , You can do off screen list items ItemView You don't have to enter the screen bindView Fast reuse ;

    2. mRecyclerPool It can provide multiple RecyclerView The common use , In certain situations , Such as viewpaper+ There are advantages under multiple list pages . Objective to ,RecyclerView In a specific scenario, to ListView The cache mechanism has been strengthened and improved .

Different use scenarios : The list page displays the interface , Need to support animation , Or frequent updates , Partial refresh , It is recommended to use RecyclerView, Stronger and better , Easy to expand ; Other circumstances ( Such as wechat card package list page ) Both OK, but ListView It will be more convenient to use , quick .


Reference article

RecyclerView So many graphs loaded , Why not collapse ?

RecyclerView Source code analysis ( Two ) —— More articles on caching mechanism

  1. jQuery1.9.1 Source code analysis -- Data caching Data modular

    jQuery1.9.1 Source code analysis -- Data caching Data modular Read the directory jQuery API in Data The basic use of jQuery.acceptData(elem) Source code analysis ...

  2. Fresco Source code analysis ( Two ) Fresco The client interacts with the server (1) Solve the legacy of Q1 problem

    4.2 Fresco The interaction between client and server ( One ) solve Q1 problem Start with this blog , Let's talk about how the client and the server interact , This interaction portal , We from Q1 Start with the question ( Blogs start with questions like this , Because I was also from here ...

  3. lodash Further encapsulation of cache usage in source code analysis

    Among all the nations in the world , It's not nature that dominates their choice , It's their point of view . -- Rousseau < Society and contract theory > This article is for reading lodash The ninth source code , Subsequent articles will be updated to this repository , welcome star:po ...

  4. 【 turn 】MaBatis Study --- Source code analysis MyBatis Caching principle

    [ original text ] Source code analysis MyBatis Caching principle 1. brief introduction stay Web Application , Caching is an essential component . We usually use ...

  5. frame -springmvc Source code analysis ( Two )

    frame -springmvc Source code analysis ( Two ) Reference resources : ...

  6. kernel 3.10 Kernel source code analysis --hung task Mechanism

    kernel 3.10 Kernel source code analysis --hung task Mechanism One . Related knowledge : For a long time , be in D state (TASK_UNINTERRUPTIBLE state ) The process of It's all vexing , be in D The state of the process cannot be connected ...

  7. Ten 、Spring And BeanFactory Source code analysis ( Two )

    Spring And BeanFactory Source code analysis ( Two ) Preface In front of us, we briefly analyzed BeanFactory Structure ,ListableBeanFactory,HierarchicalBeanFactory,A ...

  8. Vue Source code analysis ( Two ) : Vue Instance mounting

    Vue Source code analysis ( Two ) : Vue Instance mounting author: @TiffanysBear Instance mount is mainly $mount Method implementation , stay src/platforms/web/entry-runtime-wi ...

  9. The beauty of multithreading 8 One AbstractQueuedSynchronizer Source code analysis &lt; Two &gt;

    Catalog AQS Source code analysis This article mainly analyzes AQS Of ConditionObject, yes AQS The inner class of , Implementation of waiting notification mechanism . 1. Condition queue Conditional queue and AQS The synchronization queue in is different , Structure diagram is as follows : Difference between them : 1. Linked list ...

  10. Tomcat Source code analysis II : Have a look first Tomcat The overall structure of

    Tomcat Source code analysis II : Have a look first Tomcat The overall structure of Tomcat Architecture diagram Let's take a look at a more classic Tomcat Architecture diagram : From this picture , We can see that Tomcat contains Server.Service.Conn ...

Random recommendation

  1. Javascript Advanced programming —— Values of basic types and reference types

    ECMAScript Variables in have two different data type values : Basic types : The value of the basic type is a simple data segment . Include :Undefined.Null.Number.Boolean.String Five kinds Reference type : Value of reference type ...

  2. mysql replace into Usage and pit

    The primary key needs to be consistent PRIMARY KEY (id) PRIMARY KEY (id, ts) pit : ...

  3. Edit Box How to make the scroll bar always below in multi line display

    The two methods : ①  CEdit *pEdit = ((CEdit*)GetDlgItem(IDC_EDIT_RXDATA)); pEdit->LineScroll(pEdit->GetLin ...

  4. SecureCRT for Linux breakthrough 30 Angels use restrictions

    Of course, there is another way , It's when you try it out i agree When the time comes , stay ~/.vandyke/Config It will generate a file SecureCRT_eval.lic, It can be restored after deletion 30 Try it out for days

  5. Theme model ( Probabilistic latent semantic analysis PLSA、 Implied Dirichlet distribution LDA)

    One .pLSA Model 1. Naive Bayes analysis (1) Can be competent in many text classification problems .(2) It can't solve the problem of polysemy and polysemy in corpus -- It's more like lexical analysis , Not semantic analysis .(3) If you use word vectors as features of a document , Polysemy and polysemy ...

  6. JavaScript Medium Prototype property Constructors And instance objects

    1 Why use prototypes ? /* * javascript among Prototype prototype object * * */ // First introduce prototype The meaning of , Why use this object // Let's first write an object-oriented constructor ...

  7. Super detailed hands to build a Vuepress Site and opening PWA Automatic deployment

    Super detailed hands to build a Vuepress Site and opening PWA Automatic deployment I wanted to write an article about before May Day Vuepress The article , As a result, friends get married and it's over . Remember to look at the precautions at the end ! Vuepress Introduce Official website :http ...

  8. TensorFlow (RNN) Deep learning two-way LSTM(BiLSTM)+CRF Realization sequence labeling Sequence tagging problem Source download stay TensorFlow (RNN) Deep learning two-way LSTM(BiLSTM)+CR ...

  9. About ARM Medium tst、cmp、bne、beq Instructions

    One . About cmp Detailed usage Suppose now AX The number in the register is 0002H,BX The number in the register is 0003H. The instructions executed are :CMP AX, BX When executing this command , Do it first AX Subtracting the number in BX Subtraction of numbers in . List the binary ...

  10. Fanvas It's a handful swf To html5 canvas The system of animation   Usage method :     Code : <!DOCTYPE html> <html> <head> ...