5分鐘帶你理解SurfaceView

補充
源碼地址:https://github.com/bravekingzhang/Analyser

在網(wǎng)上看過一些網(wǎng)友寫的SurfaceView的原理啊笙隙,示例啊趾娃,對比了下View默终,我看到了SurfaceView的一些好處

  • SurfaceView允許你在非ui線程中去繪制。
  • SurfaceView的幀率可以操作60FPS
  • 在要求實時性比較高的游戲開發(fā)中,顯然降狠,view的ondraw是滿足不了你的磷杏,這時候只能是用SurfaceView溜畅。

下面是我寫的一個自定義控件的demo:),因為模擬器錄制不了視頻极祸,所以只能給出一個靜態(tài)圖慈格,實際上的效果是,這個黃色的圓不斷變大遥金,文字像一個個字打上去的效果~~

SurfaceView測試效果

其使用步驟和自定義View非常相似浴捆。

  • 1、不同的是現(xiàn)在是繼承自SurfaceView
  • 2稿械、在初始化的時候选泻,拿到SurfaceHolder,給SurfaceHolder設(shè)置Callback
  • 3、在Callback 中去寫幾個回調(diào)方法surfaceCreated,surfaceChanged,surfaceDestroyed页眯。
  • 4梯捕、在surfaceCreated中起一個線程,在線程中使用拿到的SurfaceHolder去鎖定Canvas進(jìn)行繪圖窝撵。
  • 5傀顾、在surfaceDestroyed中結(jié)束這個繪圖線程。

基本的步驟其實就是以上5步碌奉,下面的是全部的自定義控件的實例代碼短曾,相關(guān)地方也寫明的注釋,相信很好理解

package test.tencent.com.test;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * Created by brzhang on 16/7/16.
 * Description :
 */
public class DrawView extends SurfaceView implements SurfaceHolder.Callback {

    private int mWidth;
    private int mHeight;

    private DrawThread mDrawThread;

    public DrawView(Context context) {
        this(context, null);
    }

    public DrawView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DrawView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initView();
    }

    private void initView() {
        SurfaceHolder holder = getHolder();
        holder.addCallback(this);
        mDrawThread = new DrawThread(holder);
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();
    }


    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        mDrawThread.isRunning = true;
        mDrawThread.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        mDrawThread.isRunning = false;
        //這塊的意思其實就是赐劣,等待DrawThread執(zhí)行完嫉拐,上面的isRunning其實也達(dá)到這個目的咯
        try {
            mDrawThread.join();
        } catch ( InterruptedException e ) {
            e.printStackTrace();
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // 這里的線程專門負(fù)責(zé)繪制
    ///////////////////////////////////////////////////////////////////////////
    class DrawThread extends Thread {

        SurfaceHolder surfaceHolder;
        boolean       isRunning;
        int radius = 10;
        Paint mPaintCirlce;

        Paint mPaintText;

        public DrawThread(SurfaceHolder surfaceHolder) {

            this.surfaceHolder = surfaceHolder;
            isRunning = false;

            mPaintCirlce = new Paint();
            mPaintCirlce.setStrokeWidth(4);
            mPaintCirlce.setColor(Color.YELLOW);
            mPaintCirlce.setStyle(Paint.Style.FILL_AND_STROKE);

            mPaintText = new Paint();
            mPaintText.setTextSize(24);

        }

        @Override
        public void run() {

            Canvas c = null;

            while (isRunning) {

                try {
                    synchronized (surfaceHolder) {

                        c = surfaceHolder.lockCanvas(null);
                        doDraw(c);
                        //通過它來控制幀數(shù)執(zhí)行一次繪制后休息500ms,實際上,我們知道魁兼,ondraw如果保證60FPS的話婉徘,看到的畫面會比較流暢
                        //因此,這里璃赡,可能就是16ms咯判哥,但是,我們這里完全可以設(shè)置的比16ms都小碉考,知道surface的好處了吧塌计。
                        Thread.sleep(500);
                    }
                } catch ( InterruptedException e ) {
                    e.printStackTrace();
                } finally {
                    surfaceHolder.unlockCanvasAndPost(c);
                }

            }

        }

        public void doDraw(Canvas c) {

            //這個很重要,清屏操作侯谁,清楚掉上次繪制的殘留圖像锌仅,這里和view的ondraw不一樣,view的ondraw每次執(zhí)行之前墙贱,實際上會自動替你清除之前畫的热芹。
            c.drawColor(Color.WHITE);
            c.translate(mWidth / 2, mHeight / 2); //這里將畫筆放到view的中間

            c.drawCircle(0, 0, radius++, mPaintCirlce);

            String text = "這里是surface測試ooo";

            c.drawText(text.substring(0,radius % text.length()+1), -mPaintText.measureText(text.substring(0,radius % text.length()+1)) / 2, 0f, mPaintText);

            if (radius > mWidth / 2) {
                radius = 10;
            }

        }

    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市惨撇,隨后出現(xiàn)的幾起案子伊脓,更是在濱河造成了極大的恐慌,老刑警劉巖魁衙,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件报腔,死亡現(xiàn)場離奇詭異,居然都是意外死亡剖淀,警方通過查閱死者的電腦和手機纯蛾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來纵隔,“玉大人翻诉,你說我怎么就攤上這事炮姨。” “怎么了碰煌?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵舒岸,是天一觀的道長。 經(jīng)常有香客問我拄查,道長吁津,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任堕扶,我火速辦了婚禮,結(jié)果婚禮上梭依,老公的妹妹穿的比我還像新娘稍算。我一直安慰自己,他們只是感情好役拴,可當(dāng)我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布糊探。 她就那樣靜靜地躺著,像睡著了一般河闰。 火紅的嫁衣襯著肌膚如雪科平。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天姜性,我揣著相機與錄音瞪慧,去河邊找鬼。 笑死部念,一個胖子當(dāng)著我的面吹牛弃酌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播儡炼,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼妓湘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了乌询?” 一聲冷哼從身側(cè)響起榜贴,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎妹田,沒想到半個月后唬党,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡秆麸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年初嘹,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沮趣。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡屯烦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情驻龟,我是刑警寧澤温眉,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站翁狐,受9級特大地震影響类溢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜露懒,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一闯冷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧懈词,春花似錦蛇耀、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拒啰。三九已至表制,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間留夜,已是汗流浹背崎脉。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工拧咳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人荧嵌。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓呛踊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親啦撮。 傳聞我的和親對象是個殘疾皇子谭网,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容