1. 程式人生 > >Android SVG動畫PathView原始碼解析與使用教程(API 14)

Android SVG動畫PathView原始碼解析與使用教程(API 14)

使用的是一個第三方庫android-pathview主要是一個自定義View——PathView,跟所有自定義View一樣,重寫了三個構造方法。並且最終呼叫三個引數的構造方法,在裡面獲取自定義屬性。

/**
     * Default constructor.
     *
     * @param context The Context of the application.
     */
    public PathView(Context context) {
        this(context, null);
    }

    /**
     * Default constructor.
     *
     * @param
context The Context of the application. * @param attrs attributes provided from the resources. */
public PathView(Context context, AttributeSet attrs) { this(context, attrs, 0); } /** * Default constructor. * * @param context The Context of the application. * @param
attrs attributes provided from the resources. * @param defStyle Default style. */
public PathView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); paint.setStyle(Paint.Style.STROKE); getFromAttributes(context, attrs); }

檢視自定義屬性的xml,裡面共三個自定義屬性,pathColor為路徑顏色,預設值為綠色0xff00ff00,pathWidth為路徑寬度,預設值為8.0f,svg為路徑檔案

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="PathView">
        <attr name="pathColor" format="color"/>
        <attr name="pathWidth" format="float"/>
        <attr name="svg" format="reference"/>
    </declare-styleable>
</resources>

通過getFromAttributes函式獲得這些自定屬性,並賦值給成員變數,最後通過finally塊回收資源

 /**
     * Get all the fields from the attributes .
     *
     * @param context The Context of the application.
     * @param attrs   attributes provided from the resources.
     */
    private void getFromAttributes(Context context, AttributeSet attrs) {
        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PathView);
        try {
            if (a != null) {
                paint.setColor(a.getColor(R.styleable.PathView_pathColor, 0xff00ff00));
                paint.setStrokeWidth(a.getFloat(R.styleable.PathView_pathWidth, 8.0f));
                svgResourceId = a.getResourceId(R.styleable.PathView_svg, 0);
            }
        } finally {
            if (a != null) {
                a.recycle();
            }
        }
    }

至於成員變數,這裡貼出所有成員變數,具體作用見註釋

/**
     * Logging tag.
     */
    public static final String LOG_TAG = "PathView";
    /**
     * The paint for the path.
     */
    private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    /**
     * Utils to catch the paths from the svg.
     */
    private final SvgUtils svgUtils = new SvgUtils(paint);
    /**
     * All the paths provided to the view. Both from Path and Svg.
     */
    private List<SvgUtils.SvgPath> paths = new ArrayList<SvgUtils.SvgPath>(0);
    /**
     * This is a lock before the view is redrawn
     * or resided it must be synchronized with this object.
     */
    private final Object mSvgLock = new Object();
    /**
     * Thread for working with the object above.
     */
    private Thread mLoader;

    /**
     * The svg image from the raw directory.
     */
    private int svgResourceId;
    /**
     * Object that build the animation for the path.
     */
    private AnimatorBuilder animatorBuilder;
    /**
     * The progress of the drawing.
     */
    private float progress = 0f;

    /**
     * If the used colors are from the svg or from the set color.
     */
    private boolean naturalColors;
    /**
     * If the view is filled with its natural colors after path drawing.
     */
    private boolean fillAfter;
    /**
     * The width of the view.
     */
    private int width;
    /**
     * The height of the view.
     */
    private int height;

然後是一些getter和setter方法。

    /**
     * Set paths to be drawn and animated.
     *
     * @param paths - Paths that can be drawn.
     */
    public void setPaths(final List<Path> paths) {
        for (Path path : paths) {
            this.paths.add(new SvgUtils.SvgPath(path, paint));
        }
        synchronized (mSvgLock) {
            updatePathsPhaseLocked();
        }
    }

    /**
     * Set path to be drawn and animated.
     *
     * @param path - Paths that can be drawn.
     */
    public void setPath(final Path path) {
        paths.add(new SvgUtils.SvgPath(path, paint));
        synchronized (mSvgLock) {
            updatePathsPhaseLocked();
        }
    }
    /**
     * If the real svg need to be drawn after the path animation.
     *
     * @param fillAfter - boolean if the view needs to be filled after path animation.
     */
    public void setFillAfter(final boolean fillAfter) {
        this.fillAfter = fillAfter;
    }
    /**
     * Animator for the paths of the view.
     *
     * @return The AnimatorBuilder to build the animation.
     */
    public AnimatorBuilder getPathAnimator() {
        if (animatorBuilder == null) {
            animatorBuilder = new AnimatorBuilder(this);
        }
        return animatorBuilder;
    }
   /**
     * Get the path color.
     *
     * @return The color of the paint.
     */
    public int getPathColor() {
        return paint.getColor();
    }

    /**
     * Set the path color.
     *
     * @param color -The color to set to the paint.
     */
    public void setPathColor(final int color) {
        paint.setColor(color);
    }

    /**
     * Get the path width.
     *
     * @return The width of the paint.
     */
    public float getPathWidth() {
        return paint.getStrokeWidth();
    }

    /**
     * Set the path width.
     *
     * @param width - The width of the path.
     */
    public void setPathWidth(final float width) {
        paint.setStrokeWidth(width);
    }

    /**
     * Get the svg resource id.
     *
     * @return The svg raw resource id.
     */
    public int getSvgResource() {
        return svgResourceId;
    }

    /**
     * Set the svg resource id.
     *
     * @param svgResource - The resource id of the raw svg.
     */
    public void setSvgResource(int svgResource) {
        svgResourceId = svgResource;
    }
    /**
     * If the real svg need to be drawn after the path animation.
     *
     * @param fillAfter - boolean if the view needs to be filled after path animation.
     */
    public void setFillAfter(final boolean fillAfter) {
        this.fillAfter = fillAfter;
    }
    /**
     * Animate this property. It is the percentage of the path that is drawn.
     * It must be [0,1].
     *
     * @param percentage float the percentage of the path.
     */
    public void setPercentage(float percentage) {
        if (percentage < 0.0f || percentage > 1.0f) {
            throw new IllegalArgumentException("setPercentage not between 0.0f and 1.0f");
        }
        progress = percentage;
        synchronized (mSvgLock) {
            updatePathsPhaseLocked();
        }
        invalidate();
    }

然後通過一個函式進行路徑的更新

 /**
     * This refreshes the paths before draw and resize.
     */
    private void updatePathsPhaseLocked() {
        final int count = paths.size();
        for (int i = 0; i < count; i++) {
            SvgUtils.SvgPath svgPath = paths.get(i);
            svgPath.path.reset();
            svgPath.measure.getSegment(0.0f, svgPath.length * progress, svgPath.path, true);
            // Required only for Android 4.4 and earlier
            svgPath.path.rLineTo(0.0f, 0.0f);
        }
    }

接著就一大堆measure啊,draw啊

 @Override
    protected void onSizeChanged(final int w, final int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        if (mLoader != null) {
            try {
                mLoader.join();
            } catch (InterruptedException e) {
                Log.e(LOG_TAG, "Unexpected error", e);
            }
        }
        if (svgResourceId != 0) {
            mLoader = new Thread(new Runnable() {
                @Override
                public void run() {

                    svgUtils.load(getContext(), svgResourceId);

                    synchronized (mSvgLock) {
                        width = w - getPaddingLeft() - getPaddingRight();
                        height = h - getPaddingTop() - getPaddingBottom();
                        paths = svgUtils.getPathsForViewport(width, height);
                        updatePathsPhaseLocked();
                    }
                }
            }, "SVG Loader");
            mLoader.start();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (svgResourceId != 0) {
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
            setMeasuredDimension(widthSize, heightSize);
            return;
        }

        int desiredWidth = 0;
        int desiredHeight = 0;
        final float strokeWidth = paint.getStrokeWidth() / 2;
        for (SvgUtils.SvgPath path : paths) {
            desiredWidth += path.bounds.left + path.bounds.width() + strokeWidth;
            desiredHeight += path.bounds.top + path.bounds.height() + strokeWidth;
        }
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(widthMeasureSpec);

        int measuredWidth, measuredHeight;

        if (widthMode == MeasureSpec.AT_MOST) {
            measuredWidth = desiredWidth;
        } else {
            measuredWidth = widthSize;
        }

        if (heightMode == MeasureSpec.AT_MOST) {
            measuredHeight = desiredHeight;
        } else {
            measuredHeight = heightSize;
        }

        setMeasuredDimension(measuredWidth, measuredHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        synchronized (mSvgLock) {
            canvas.save();
            canvas.translate(getPaddingLeft(), getPaddingTop());
            final int count = paths.size();
            for (int i = 0; i < count; i++) {
                final SvgUtils.SvgPath svgPath = paths.get(i);
                final Path path = svgPath.path;
                final Paint paint1 = naturalColors ? svgPath.paint : paint;
                canvas.drawPath(path, paint1);
            }
            fillAfter(canvas);
            canvas.restore();
        }
    }

    /**
     * If there is svg , the user called setFillAfter(true) and the progress is finished.
     *
     * @param canvas Draw to this canvas.
     */
    private void fillAfter(final Canvas canvas) {
        if (svgResourceId != 0 && fillAfter && progress == 1f) {
            svgUtils.drawSvgAfter(canvas, width, height);
        }
    }

我們看到他重寫了onSizeChanged方法,首先判斷執行緒是否是null,如果不為null,則呼叫join方法,讓該thread執行完run方法裡面的東西后,再執行join()方法後面的程式碼。後面的程式碼就是起了一個執行緒獲取寬度,高度,路徑並更新路徑等資訊。

onMeasure()方法裡就是一些測量內容了。具體測量邏輯見原始碼。

onDraw()方法主要完成繪製,其實很簡單,就是在Canvas上畫圖,遍歷所有Path,畫在畫布上,畫完後呼叫了fillAfter方法,如果設定了svg資源,以及fillAfter 成員變數為true,動畫已完成,則會保持動畫

最後這個自定義View類裡使用了建立者模式進行建立路徑動畫,比如動畫的時間,插值器,延時,監聽器等等。

/**
     * Object for building the animation of the path of this view.
     */
    public static class AnimatorBuilder {
        /**
         * Duration of the animation.
         */
        private int duration = 350;
        /**
         * Interpolator for the time of the animation.
         */
        private Interpolator interpolator;
        /**
         * The delay before the animation.
         */
        private int delay = 0;
        /**
         * ObjectAnimator that constructs the animation.
         */
        private final ObjectAnimator anim;
        /**
         * Listener called before the animation.
         */
        private ListenerStart listenerStart;
        /**
         * Listener after the animation.
         */
        private ListenerEnd animationEnd;
        /**
         * Animation listener.
         */
        private PathViewAnimatorListener pathViewAnimatorListener;

        /**
         * Default constructor.
         *
         * @param pathView The view that must be animated.
         */
        public AnimatorBuilder(final PathView pathView) {
            anim = ObjectAnimator.ofFloat(pathView, "percentage", 0.0f, 1.0f);
        }

        /**
         * Set the duration of the animation.
         *
         * @param duration - The duration of the animation.
         * @return AnimatorBuilder.
         */
        public AnimatorBuilder duration(final int duration) {
            this.duration = duration;
            return this;
        }

        /**
         * Set the Interpolator.
         *
         * @param interpolator - Interpolator.
         * @return AnimatorBuilder.
         */
        public AnimatorBuilder interpolator(final Interpolator interpolator) {
            this.interpolator = interpolator;
            return this;
        }

        /**
         * The delay before the animation.
         *
         * @param delay - int the delay
         * @return AnimatorBuilder.
         */
        public AnimatorBuilder delay(final int delay) {
            this.delay = delay;
            return this;
        }

        /**
         * Set a listener before the start of the animation.
         *
         * @param listenerStart an interface called before the animation
         * @return AnimatorBuilder.
         */
        public AnimatorBuilder listenerStart(final ListenerStart listenerStart) {
            this.listenerStart = listenerStart;
            if (pathViewAnimatorListener == null) {
                pathViewAnimatorListener = new PathViewAnimatorListener();
                anim.addListener(pathViewAnimatorListener);
            }
            return this;
        }

        /**
         * Set a listener after of the animation.
         *
         * @param animationEnd an interface called after the animation
         * @return AnimatorBuilder.
         */
        public AnimatorBuilder listenerEnd(final ListenerEnd animationEnd) {
            this.animationEnd = animationEnd;
            if (pathViewAnimatorListener == null) {
                pathViewAnimatorListener = new PathViewAnimatorListener();
                anim.addListener(pathViewAnimatorListener);
            }
            return this;
        }

        /**
         * Starts the animation.
         */
        public void start() {
            anim.setDuration(duration);
            anim.setInterpolator(interpolator);
            anim.setStartDelay(delay);
            anim.start();
        }

        /**
         * Animation listener to be able to provide callbacks for the caller.
         */
        private class PathViewAnimatorListener implements Animator.AnimatorListener {

            @Override
            public void onAnimationStart(Animator animation) {
                if (listenerStart != null) listenerStart.onAnimationStart();
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                if (animationEnd != null) animationEnd.onAnimationEnd();
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        }

        /**
         * Called when the animation start.
         */
        public interface ListenerStart {
            /**
             * Called when the path animation start.
             */
            void onAnimationStart();
        }

        /**
         * Called when the animation end.
         */
        public interface ListenerEnd {
            /**
             * Called when the path animation end.
             */
            void onAnimationEnd();
        }
    }

SVG檔案的載入等工作都在SvgUtils類中完成。依賴了一個jar包,該工具類主要負責資原始檔的載入和初始化

構造方法是傳入一個畫筆

    /** 
     * Init the SVGUtils with a paint for coloring. 
     * 
     * @param sourcePaint - the paint for the coloring. 
     */ 
    public SvgUtils(final Paint sourcePaint) {
        mSourcePaint = sourcePaint;
    } 

資原始檔的載入

    /** 
     * Loading the svg from the resources. 
     * 
     * @param context     Context object to get the resources. 
     * @param svgResource int resource id of the svg. 
     */ 
    public void load(Context context, int svgResource) {
        if (mSvg != null) return;
        try { 
            mSvg = SVG.getFromResource(context, svgResource);
            mSvg.setDocumentPreserveAspectRatio(PreserveAspectRatio.UNSCALED);
        } catch (SVGParseException e) {
            Log.e(LOG_TAG, "Could not load specified SVG resource", e);
        } 
    } 

其餘的方法就是跟繪製有關了。有興趣自己去下原始碼看看。這裡不做展開了。

原始碼解析完畢後,我們使用一下這個庫。我們首先使用github上的svg檔案做測試。

在佈局檔案中新增程式碼

    <com.eftimoff.androipathview.PathView
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/pathView"
        android:layout_width="150dp"
        android:layout_height="150dp"
        app:svg="@raw/monitor"
        app:pathWidth="2"
        app:pathColor="#ff0000"
        />

然後就可以通過getPathAnimator方法獲得建立者物件,通過一系列的鏈式呼叫配置動畫,比如延時,動畫持續時間,插值器,監聽器,最後呼叫start開始動畫。


PathView mPathView= (PathView) findViewById(R.id.pathView);
mPathView.getPathAnimator()
.delay(1000)
.duration(3000)
.interpolator(new BounceInterpolator())
.listenerStart(new PathView.AnimatorBuilder.ListenerStart() {
    @Override
    public void onAnimationStart() {
        Log.e("TAG", "start");
    }
})
.listenerEnd(new PathView.AnimatorBuilder.ListenerEnd() {
    @Override
    public void onAnimationEnd() {
        Log.e("TAG","end");
    }
}).start();

最終效果就是這樣子

這裡寫圖片描述

當然我們也可以使用svg檔案裡的顏色,讓它繪製完成後繪製最終真正的svg,可以加入以下程式碼

mPathView.useNaturalColors();
mPathView.setFillAfter(true);

最終效果如下
這裡寫圖片描述

當然你可能想讓它停留在某個狀態點,你可以使用以下函式進行設定,引數值範圍為0到1

mPathView.setPercentage(0.8f);

甚至你可以不用svg檔案,你可以使用Path類

Path path=new Path();
path.moveTo(0.0f, 0.0f);
path.lineTo(length / 4f, 0.0f);
path.lineTo(length, height / 2.0f);
path.lineTo(length / 4f, height);
path.lineTo(0.0f, height);
path.lineTo(length * 3f / 4f, height / 2f);
path.lineTo(0.0f, 0.0f);
path.close();
mPathView.setPath(path);

還有List型別

List<Path> paths = new ArrayList<Path>();
//to do paths.add(path)
mPathView.setPaths(paths);

當然對於自定義屬性,也可以通過程式碼設定

mPathView.setPathColor(0x00ff00);
mPathView.setPathWidth(5f);
mPathView.setSvgResource(R.raw.logout);

最後貼一下svg的一些命令,每個命令都有大小寫形式,大寫代表後面的引數是絕對座標,小寫表示相對座標。引數之間用空格或逗號隔開

  • M: move to 移動繪製點
  • L:line to 直線
  • Z:close 閉合
  • C:cubic bezier 三次貝塞爾曲線
  • Q:quatratic bezier 二次貝塞爾曲線
  • A:ellipse 圓弧

詳解

  • M (x y) 移動到x,y
  • L (x y) 直線連到x,y,還有簡化命令H(x) 水平連線、V(y)垂直連線
  • Z,沒有引數,連線起點和終點
  • C(x1 y1 x2 y2 x y),控制點x1,y1 x2,y2,終點x,y
  • Q(x1 y1 x y),控制點x1,y1,終點x,y
  • A(rx ry x-axis-rotation large-arc-flag sweep-flag x y)
    rx ry 橢圓半徑
    x-axis-rotation x軸旋轉角度
    large-arc-flag 為0時表示取小弧度,1時取大弧度
    sweep-flag 0取逆時針方向,1取順時針方向
    這裡寫圖片描述

更多詳情請參考w3c

相關推薦

Android SVG動畫PathView原始碼解析使用教程API 14

使用的是一個第三方庫android-pathview主要是一個自定義View——PathView,跟所有自定義View一樣,重寫了三個構造方法。並且最終呼叫三個引數的構造方法,在裡面獲取自定義屬性。 /** * Default construct

Java併發程式設計高階技術-高效能併發框架原始碼解析實戰資源同步

第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級資料進行壓力測試。讓大

2018最新Java併發程式設計高階技術-高效能併發框架原始碼解析實戰已完結

第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級資料進行壓力測試。讓大

Java併發程式設計高階技術-高效能併發框架原始碼解析實戰資源連結

第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級

Java併發程式設計高階技術-高效能併發框架原始碼解析實戰已完結2018最全

1.背景 匿名內部類有以下問題: 語法過於冗餘 匿名類中的this和變數名容易使人產生誤解 型別載入和例項建立語義不夠靈活 無法捕獲非final的區域性變數 無法對控制流進行抽象 lambda表示式提供了輕量級的語法。 2.語法 lambda表示式的語法由引數列表、箭頭符號->和函式體

2019最新Java併發程式設計高階技術-高效能併發框架原始碼解析實戰已完結

第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級資料進行壓力測試。讓大

Java併發程式設計高階技術-高效能併發框架原始碼解析實戰無密連結

第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級資料進行壓力測試。讓大

Java併發程式設計高階技術-高效能併發框架原始碼解析實戰雲盤分享

第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級

某網Java併發程式設計高階技術-高效能併發框架原始碼解析實戰雲盤下載

第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級

Selenium2Library原始碼解析擴充套件

一直覺得Selenium2Library對selenium的封裝很贊,最近模擬它的結構封裝給一個同事寫了個C# selenium的demo,過程中看了細看了一部分原始碼。加上之前封裝的內容,分享一波。 注1:以下涉及到RF的指令碼全未加延時sleep,如需除錯

Java併發程式設計高階技術-高效能併發框架原始碼解析實戰目前最全

第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級

Python核心原始碼解析C/CPP-API拓展程式設計PyObject

開發十年,就只剩下這套架構體系了! >>>   

React 伺服器渲染原理解析實踐同步更新

第1章 伺服器端渲染基礎本章主要講解客戶端與伺服器端渲染的概念,分析客戶端渲染和伺服器端渲染的利弊,帶大家對伺服器端渲染有一個粗淺認識。 1-1 課程導學1-2 什麼是伺服器端渲染1-3 什麼是客戶端渲染1-4 React 客戶端渲染的優勢與弊端 第2章 React中的伺服器端渲染本章將藉助Node.js

redis原始碼分析思考十九——AOF持久化

    為了解決持久化檔案很龐大以及會阻塞伺服器的 情況,redis提出一種新的持久化方案:AOF持久化。AOF持久化是redis儲存資料的另外一種方式,全稱Append Only File,與RDB持久化不同的是,AOF持久化是隻儲存從客戶端鍵入

redis原始碼分析思考十八——RDB持久化

    redis是一個鍵值對的資料庫伺服器,伺服器中包含著若干個非空的資料庫,每個非空資料庫裡又包含著若干個鍵值對。因為redis是一個基於記憶體存貯的資料庫,他將自己所存的資料存於記憶體中,如果不將這些資料及時的儲存在硬碟中,當電腦關機或者進行

redis原始碼分析思考十七——有序集合型別的命令實現(t_zset.c)

    有序集合是集合的延伸,它儲存著集合元素的不可重複性,但不同的是,它是有序的,它利用每一個元素的分數來作為有序集合的排序依據,現在列出有序集合的命令: 有序集合命令 命令 對應操作 時

redis原始碼分析思考十六——集合型別的命令實現(t_set.c)

    集合型別是用來儲存多個字串的,與列表型別不一樣,集合中不允許有重複的元素,也不能以索引的方式來通過下標獲取值,集合中的元素還是無序的。在普通的集合上增刪查改外,集合型別還實現了多個集合的取交集、並集、差集,集合的命令如下表所示: 集合命

redis原始碼分析思考十五——雜湊型別的命令實現(t_hash.c)

    雜湊型別又叫做字典,在redis中,雜湊型別本身是一個鍵值對,而雜湊型別裡面也存貯著鍵值對,其對應關係是,每個雜湊型別的值對應著一個鍵值對或多對鍵值對,如圖所示: 雜湊型別命令 命令 對應操

redis原始碼分析思考十四——列表型別的命令實現(t_list.c)

    列表型別是用來存貯多個字串物件的結構。一個列表可以存貯232-1個元素,可以對列表兩端進行插入(push)、彈出(pop),還可以獲取指定範圍內的元素列表、獲取指定索引的元素等等,它可以靈活的充當棧和佇列的角色。下面列出列表的命令: 列

反向解析PTRPointer Record

郵件 無法 部分 csdn rfc 交換 china eve you PTR記錄,是電子郵件系統中的郵件交換記錄的一種;另一種郵件交換記錄是A記錄(在IPv4協議中)或AAAA記錄(在IPv6協議中)。PTR記錄常被用於反向地址解析。 PTR記錄