1. Basic Concepts
1. Definition:
Defines a series of algorithms, encapsulates each algorithm, and makes them interchangeable. The policy pattern lets the algorithm transform independently of the client that uses it.
2. Class Diagram
- Context object: encapsulates possible policy changes and blocks direct access to the algorithm by other modules
- Stategy Abstract policy: Defines common algorithm rules
- ConcreteStategy Concrete Policy: Contains concrete algorithms
3. Application Scenarios:
- Hide algorithm implementation details from callers
- There are multiple methods to solve the same problem. You need to select one method in the form of if and else
4. Advantages:
- Avoid if else statements with multiple processing methods. Easy to expand, more than one way of processing, more than one implementation class
- The structure is more clear, better encapsulation
5. Disadvantages:
Too many algorithms will result in multiple algorithm implementation classes. Context needs to know all the algorithms and make the call accordingly.
Ii. Examples:
For example, renting a house can be through various channels, including agents, landlords, friends and so on. Each approach can be used as a strategy and can be switched.
1. Abstract Strategy:
public interface RentingStrategy {
void renting();
}
Copy the code
2. Specific strategies
Mediation:
Public class AgencyStrategy implements RentingStrategy {@override public void renting() {system.out.println (" renting through an agent "); }}Copy the code
Landlord:
public class LandlordStrategy implements RentingStrategy { @Override public void renting() { System.out.println(" rent through landlord "); }}Copy the code
Friend:
Public class FriendStrategy implements RentingStrategy {@override public void renting() {system.out.println (" renting through a friend "); }}Copy the code
3, the Context
public class Context { private RentingStrategy mRentingStrategy; public Context(RentingStrategy rentingStrategy) { this.mRentingStrategy = rentingStrategy; } public void rentHouse() { this.mRentingStrategy.renting(); }}Copy the code
4, call
public class StrategyTest{ public static void main(String[] args) { RentingStrategy friendStrategy = new FriendStrategy(); Context context = new Context(friendStrategy); context.rentHouse(); }}Copy the code
Three, animation interpolator
The animation interpolator is used to calculate the percentage change in the current property value based on the percentage of time elapsed. Such as LinearInterpolator for uniform animation, AccelerateDecelerateInterpolator for acceleration deceleration animation and so on.
1, the Interpolator
Public interface Interpolator extends TimeInterpolator {} public interface Interpolator extends TimeInterpolator {/** * Returns the percentage of elapsed time */ float getInterpolation(float input); }Copy the code
Define the methods that interfaces and policies can provide
2, LinearInterpolator
@HasNativeInterpolator public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { public LinearInterpolator() { } public LinearInterpolator(Context context, AttributeSet attrs) { } public float getInterpolation(float input) { return input; }}Copy the code
3, AccelerateDecelerateInterpolator
@HasNativeInterpolator public class AccelerateDecelerateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { public AccelerateDecelerateInterpolator() { } @SuppressWarnings({"UnusedDeclaration"}) public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) { } public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0 f) + 0.5 f; }}Copy the code
The difference between different interpolators is that the return value of getInterpolation is different, that is to say, the algorithm is different.
4. Interpolator call
(1) setInterpolator sets interpolation
#Animation
public void setInterpolator(Interpolator i) {
mInterpolator = i;
}
Copy the code
Interpolator Sets an interpolator (a policy) by setInterpolator
(2) startAnimation of View
#View public void startAnimation(Animation animation) { animation.setStartTime(Animation.START_ON_FIRST_FRAME); // Set the animation setAnimation(animation); // Refresh parent cache invalidateParentCaches(); // Refresh the View and its subview invalidate(true); }Copy the code
Invalidate redraws the View and calls the View’s draw method (3) draw
boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) { ...... final Animation a = getAnimation(); if (a ! = null) { more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired); . }}Copy the code
private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime, Animation a, boolean scalingRequired) { ...... // Set the animation to listen onAnimationStart(); }... invalidationTransform = parent.mInvalidationTransformation; A.gaettransformation (drawingTime, invalidationTransform, 1f); } else { invalidationTransform = t; } if (more) { ...... Final RectF Region = parent.minvalidateregion; a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region, invalidationTransform); parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION; Final int left = mLeft + (int) region.left; final int left = mLeft + (int) region.left; final int top = mTop + (int) region.top; Parent.invalidate (left, top, left + (int) (region.width() +.5f), top + (int) (region.height() +.5f))); } } return more; }Copy the code
(4) Animation. GetTransformation realized the change of the specific value of the Animation
public boolean getTransformation(long currentTime, Transformation outTransformation) { ...... / / by interpolation, percentage for animation to perform final float interpolatedTime = mInterpolator. GetInterpolation (normalizedTime); applyTransformation(interpolatedTime, outTransformation); }... return mMore; }Copy the code
Interpolator’s getInterpolation method is Interpolator internally to get the animation execution percentage