Spring Cache invalidate()
Spring Cache invalidate() Invalidate the cache through removing all mappings, expecting all entries to be immediately invisible for subsequent lookups.
Syntax
The method invalidate() from Cache is declared as:
default boolean invalidate()
The method invalidate() returns true if the cache was known to have mappings before, false if it did not (or if prior presence of entries could not be determined)
Example
The following code shows how to use Spring Cache invalidate()
import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.UUID; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import com.oup.ehcache.bo.SampleBO; @SpringBootApplication// w w w . d e m o2 s .c o m public class EhCaccheApplication < Logger logger = org.slf4j.LoggerFactory.getLogger(this.getClass()); HashMapString, SampleBO> tempStorage = new HashMapString, SampleBO>(); public static void main(String[] args) < SpringApplication.run(EhCaccheApplication.class, args); > @Autowired private CacheManager cacheManager; @Autowired @Qualifier("springManagedSampleBL") private SampleBL sampleBL; @Bean public CommandLineRunner commandLineRunner2(ApplicationContext ctx) < return args -> < sampleBL.getAll(); logger.debug("Calling second time------------"); sampleBL.getAll(); logger.debug("Calling third time------------"); sampleBL.getAll(); logger.debug("Calling fourth time------------"); sampleBL.getAll(); logger.debug("Flushing the cache"); cacheManager.getCache("oup-cache-allItemsCache").invalidate(); logger.debug("Cache flushed"); logger.debug("Calling fifth time------------"); sampleBL.getAll(); >; > @SuppressWarnings("unused") //@Bean public CommandLineRunner commandLineRunner1(ApplicationContext ctx) < return args -> < byte[] content = org.apache.commons.io.FileUtils.readFileToByteArray(new File("C:\\SKG\\1")); Cache cache = cacheManager.getCache("oup-cache-advantageFeedsCache"); for (int iRun = 0; iRun < 5; iRun++) < ArrayListString> keys = new ArrayList<>(); for (int iCounter = 0; iCounter < 7; iCounter++) < SampleBO sampleBO = new SampleBO(UUID.randomUUID().toString(), content); // tempStorage.put(sampleBO.getKey(), sampleBO); cache.put(sampleBO.getKey(), sampleBO); keys.add(sampleBO.getKey()); System.out.println("Adding. "); > //Get all elements from cache -->https://stackoverflow.com/questions/11829383/how-to-iterate-on-a-cache-entries/11829972 keys.forEach(item -> < if (cache.get(item) != null) < System.out.println(item); > else < System.out.println("Item not found:" + item); > >); cache.invalidate(); Thread.sleep(30000); > // Thread.sleep(300000); >; > >
Related
demo2s.com | Email: | Demo Source and Support. All rights reserved.
Android custom View invalidate method and postInvalidate method
When we customize a View, we have to use the invalidate method. This method is used to refresh the View and redraw it. The postInvalidate method, however, may not be as familiar because it is used relatively often in development. PostInvalidate: postInvalidate: postInvalidate: postInvalidate: postInvalidate: postInvalidate: postInvalidate: postInvalidate: postInvalidate: postInvalidate: postInvalidate
So what’s the difference between an invalidate method and a postInvalidate method?
The difference between the invalidate and postInvalidate methods
In fact, the answer is also very simple, in one sentence:
Both the invalidate method and the postInvalidate method are used to refresh the View. The invalidate method is used in the UI thread, and the postInvalidate method is used in the non-UI thread to switch the thread to the UI thread. The postInvalidate method finally calls the invalidate method.
Of course, empty words have no basis, we still come to see the source code
Invalidate method and postInvalidate method source analysis
Let’s first look at the postInvalidate method in the View
@UiThread public class View implements Drawable.Callback, KeyEvent.Callback,AccessibilityEventSource < . public void postInvalidate() < postInvalidateDelayed(0); >public void postInvalidate(int left, int top, int right, int bottom) < postInvalidateDelayed(0, left, top, right, bottom); >public void postInvalidateDelayed(long delayMilliseconds) < final AttachInfo attachInfo = mAttachInfo; if(attachInfo ! = null) < attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds); >>. >Copy the code
We can see from the source, the last call postInvalidate method ViewRootImpl dispatchInvalidateDelayed method
//ViewRootImpl.class final ViewRootHandler mHandler = new ViewRootHandler(); public void dispatchInvalidateDelayed(View view, long delayMilliseconds) < Message msg = mHandler.obtainMessage(MSG_INVALIDATE, view); mHandler.sendMessageDelayed(msg, delayMilliseconds); >Copy the code
In ViewRootImpl dispatchInvalidateDelayed method is like ViewRootHandler sent a MSG_INVALIDATE message, ViewRootHandler is an internal Handler class in ViewRootImpl
final class ViewRootHandler extends Handler < @Override public String getMessageName(Message message) < switch (message.what) < case MSG_INVALIDATE: return "MSG_INVALIDATE"; . >returnsuper.getMessageName(message); >. @Override public void handleMessage(Message msg) < switch (msg.what) MSG_INVALIDATE: ((View) msg.obj).invalidate(); break; . >>>Copy the code
We can see that the MSG_INVALIDATE message is handled in the ViewRootHandler by invoking the View’s invalidate method.
conclusion
We can draw the conclusion from the above source code:
(1) postInvalidate method calls in the ViewRootImpl dispatchInvalidateDelayed method is sending a message to the ViewRootHandler ViewRootImpl, Finally, the View’s invalidate method is called.
(2) Since ViewRootImpl is in the UI thread, the postInvalidate method is used to switch the refresh operation from the non-UI thread to the UI thread, so that the INvalidate method can be invoked in the UI thread to refresh the View. So, if the View is in the UI thread, and you don’t have to use multiple threads, you can refresh the View with invalidate. This is why we rarely touch the postInvalidate method
(3) In summary, postInvalidate implements the message mechanism that allows us to call the View refresh method on non-UI threads.
Invalidate method refresh View call process analysis
//View.class @UiThread public class View implements Drawable.Callback, KeyEvent.Callback,AccessibilityEventSource < . public void invalidate() < invalidate(true); > / / invalidateCache fortrueVoid invalidate(Boolean invalidateCache) ); > void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate) < . if((mPrivateFlags (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) || (invalidateCache (mPrivateFlags PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) || (mPrivateFlags PFLAG_INVALIDATED) ! = PFLAG_INVALIDATED || (fullInvalidate isOpaque() ! = mLastIsOpaque)) (fullInvalidate) < mLastIsOpaque = isOpaque(); mPrivateFlags = ~PFLAG_DRAWN; >mPrivateFlags |= PFLAG_DIRTY; if(invalidateCache) < mPrivateFlags |= PFLAG_INVALIDATED; mPrivateFlags = ~PFLAG_DRAWING_CACHE_VALID; >// That's the point!! final AttachInfo ai = mAttachInfo; final ViewParent p = mParent;if(p ! = null ai ! = null l r t b) < final Rect damage = ai.mTmpInvalRect; damage.set(l, t, r, b); p.invalidateChild(this, damage); >. >>>Copy the code
The View’s invalidate method finally calls the invalidateInternal method, and the key logic of the invalidateInternal method is highlighted above.
- The damage variable represents the area that needs to be redrawn, which is adjusted to the parent layout during a series of calls.
- The invalidateInternal method calls the View’s parent layout method, invalidateChild, to request a redraw. So who is the parent layout of the View? There are two cases: either ViewGroup or viewrotimPL class.
Let’s take a look at the invalidateChild method in ViewGroup
@UiThread public abstract class ViewGroup extends View implements ViewParent, ViewManager < @Override public final void invalidateChild(View child, final Rect dirty) < ViewParent parent = this; final AttachInfo attachInfo = mAttachInfo; if(attachInfo ! = null) < . // This is a loop that iterates through the parent layout of the current layout View from the current layout View up to the ViewRootImpldo < View view = null; if (parent instanceof View) < view = (View) parent; >if (drawAnimation) < if(view ! = null) < view.mPrivateFlags |= PFLAG_DRAW_ANIMATION; >else if (parent instanceof ViewRootImpl) < ((ViewRootImpl) parent).mIsAnimating = true; >>. / / call here is that the parent layout method of invalidateChildInParent parent. = the parent invalidateChildInParent (location, dirty); . >while(parent ! = null); > > @Override public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) ((mPrivateFlags PFLAG_DRAWN) == PFLAG_DRAWN || (mPrivateFlags PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) < if((mGroupFlags (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE)) ! = FLAG_OPTIMIZE_INVALIDATE) < . // Here is also something to calculate the drawing areareturn mParent; > else< mPrivateFlags = ~PFLAG_DRAWN ~PFLAG_DRAWING_CACHE_VALID; . // Here is also something to calculate the drawing areareturnmParent; >>returnnull; >>Copy the code
There is a loop inside the invalidateChild method of a ViewGroup that keeps calling the invalidateChildInParent method of the parent layout, and the final parent layout of both views and Viewgroups is ViewRootImpl
So the invalidateInternal method in the View and the invalidateChild method in the ViewGroup both end up calling the ViewRootImpl method
public final class ViewRootImpl implements ViewParent,View.AttachInfo.Callbacks, ThreadedRenderer. HardwareDrawCallbacks / if there is no parent View layout, @Override public void invalidateChild(View child, Rect dirty) < invalidateChildInParent(null, dirty); > @override public ViewParent invalidateChildInParent(int[] location, Rect dirty) < checkThread(); emsp; emsp; emsp; emsp; // If dirty is null, redraw the entire area indicated by the current ViewRootImplif (dirty == null) < invalidate(); returnnull; // If dirty is empty, the calculated areas that need to be redrawn need not be drawn>else if(dirty.isEmpty() ! mIsAnimating) null; > if(mCurScrollY ! = 0 || mTranslator ! = null) < mTempRect.set(dirty); dirty = mTempRect;if(mCurScrollY ! = 0) < dirty.offset(0, -mCurScrollY); >if(mTranslator ! = null) < mTranslator.translateRectInAppWindowToScreen(dirty); >if (mAttachInfo.mScalingRequired) < dirty.inset(-1, -1); >> invalidateRectOnScreen(dirty); return null; > private void invalidateRectOnScreen(Rect dirty) < final Rect localDirty = mDirty; .if(! MWillDrawSoon (intersected | | mIsAnimating)) / call scheduleTraversals method for drawing scheduleTraversals (); > > // Draw the entire ViewRootImpl area voidinvalidate() < mDirty.set(0, 0, mWidth, mHeight); if(! MWillDrawSoon)/ Call scheduleTraversals to draw scheduleTraversals(); > >>Copy the code
As you can see in ViewRootImpl the scheduleTraversals method is called at the end to draw. As we understand the rendering process of a View, it starts with the performTraversals method of ViewRootImpl. Let’s look at the scheduleTraversals method of ViewRootImpl.
//ViewRootImpl.class void scheduleTraversals() < if(! mTraversalScheduled) < mTraversalScheduled =true; mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier(); // This is the key!! mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);if (!mUnbufferedInputDispatch) < scheduleConsumeBatchedInput(); >notifyRendererOfFramePending(); pokeDrawLockIfNeeded(); > > Copy the code
There is no performTraversals method we are looking for. But we see the scheduleTraversals method called mChoreographer. PostCallback methods, there should be a key
The Choreoprapher class orchestrates the execution of input events, animation events, and draw events, and its postCallback method puts the event to be executed into an internal queue, and finally executes the passed Runnable, in this case mTraversalRunnable. So let’s look at mTraversalRunnable
//ViewRootImpl.class final class TraversalRunnable implements Runnable < @Override public void run() < doTraversal(); > > final TraversalRunnable mTraversalRunnable = new TraversalRunnable(); void doTraversal() < if (mTraversalScheduled) < mTraversalScheduled = false; mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier); if (mProfile) < Debug.startMethodTracing("ViewAncestor"); > // Find our performTraversals method, and here is where to start rendering the View! performTraversals();if (mProfile) < Debug.stopMethodTracing(); mProfile = false; >>>Copy the code
When we call the View’s invalidate method, the View will keep calling up the parent layout drawing method and counting the areas that need to be redrawn in the process, eventually going into the View wrotimpl, The view otimpl’s Perform the redraw traversals is called.
conclusion
- When we customize a View, when we need to refresh the View in a UI thread, we call the Invalidate method directly, and in a non-UI thread, we call the postInvalidate method to refresh the View
- The postInvalidate method implements the message mechanism, and the invalidate method is ultimately called to refresh the View
- The invalidate method ends up calling performTraversals in View wrootimpl to redraw the View
Welcome to follow my wechat public number, and make progress with me every day!