android 中的view和surfaceView

Surface意為表層、表面享言,顧名思義SurfaceView就是指一個在表層的View對象市殷。為什么說是在表層呢,這是因為它有點特殊跟其他View不一樣矮湘,其他View是繪制在“表層”的上面斟冕,而它就是充當“表層”本身。SDK的文檔 說到:SurfaceView就是在窗口上挖一個洞缅阳,它就是顯示在這個洞里磕蛇,其他的View是顯示在窗口上,所以View可以顯式在 SurfaceView之上十办,你也可以添加一些層在SurfaceView之上秀撇。 從API中可以看出SurfaceView屬于View的子類 它是專門為制作游戲而產(chǎn)生的,它的功能非常強大向族,最重要的是它支持OpenGL ES庫呵燕,2D和3D的效果都可以實現(xiàn)。創(chuàng)建SurfaceView的時候需要實現(xiàn)SurfaceHolder.Callback接口件相,它可以用來監(jiān)聽SurfaceView的狀態(tài)再扭,比如:SurfaceView的改變 、SurfaceView的創(chuàng)建 夜矗、SurfaceView 銷毀等霍衫,我們可以在相應的方法中做一些比如初始化的操作或者清空的操作等等。

Android系統(tǒng)提供了View進行繪圖處理侯养,我們通過自定義的View可以滿足大部分的繪圖需求敦跌,但是這有個問題就是我們通常自定義的View是用于主動更新情況的,用戶無法控制其繪制的速度,由于View是通過invalidate方法通知系統(tǒng)去調(diào)用view.onDraw方法進行重繪柠傍,而Android系統(tǒng)是通過發(fā)出VSYNC信號來進行屏幕的重繪麸俘,刷新的時間是16ms,如果在16ms內(nèi)View完成不了執(zhí)行的操作,用戶就會看著卡頓惧笛,比如當draw方法里執(zhí)行的邏輯過多从媚,需要頻繁刷新的界面上,例如游戲界面患整,那么就會不斷的阻塞主線程拜效,從而導致畫面卡頓。而SurfaceView相當于是另一個繪圖線程各谚,它是不會阻礙主線程紧憾,并且它在底層實現(xiàn)機制中實現(xiàn)了雙緩沖機制。

這里說一下雙緩沖機制
雙緩沖甚至是多緩沖昌渤,在許多情況下都很有用赴穗。一般需要使用雙緩沖區(qū)的地方都是由于“生產(chǎn)者”和“消費者”供需不一致所造成的。這樣的情況在很多地方后可能會發(fā)生膀息,使用多緩沖可以很好的解決般眉。我舉幾個常見的例子:

例 1. 在網(wǎng)絡傳輸過程中數(shù)據(jù)的接收,有時可能數(shù)據(jù)來的太快來不及接收導致數(shù)據(jù)丟失潜支。這是由于“發(fā)送者”和“接收者”速度不一致所致甸赃,在他們之間安排一個或多個緩沖區(qū)來存放來不及接收的數(shù)據(jù),讓速度較慢的“接收者”可以慢慢地取完數(shù)據(jù)不至于丟失冗酿。

2.如何使用SurfaceView埠对?
首先SurfaceView也是一個View,它也有自己的生命周期已烤。因為它需要另外一個線程來執(zhí)行繪制操作,所以我們可以在它生命周期的初始化階 段開辟一個新線程妓羊,然后開始執(zhí)行繪制胯究,當生命周期的結束階段我們插入結束繪制線程的操作。這些是由其內(nèi)部一個SurfaceHolder對象完成的躁绸。

SurfaceView它的繪制原理是繪制前先鎖定畫布(獲取畫布)裕循,然后等都繪制結束以后在對畫布進行解鎖 ,最后在把畫布內(nèi)容顯示到屏幕上净刮。

通常情況下剥哑,使用以下步驟來創(chuàng)建一個SurfaceView的模板:(實現(xiàn)實時手繪)

222222222.jpg
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
    private static final String TAG = "SurfaceView";
    //SurfaceHolder
    private SurfaceHolder mHolder;
    //用于繪圖的Canvas
    private Canvas mCanvas;
    //子線程標志位
    private boolean mIsDrawing;
    //畫筆
    private Paint mPaint;
    //路徑
    private Path mPath;
    public MySurfaceView(Context context) {
        super(context);
        initView();
    }

    public MySurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    public MySurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    private void initView() {
        mHolder = getHolder();
        //添加回調(diào)
        mHolder.addCallback(this);
        mPath = new Path();
        //初始化畫筆
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(6);
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.RED);
        setFocusable(true);
        setFocusableInTouchMode(true);
        this.setKeepScreenOn(true);

    }

    //Surface的生命周期
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mIsDrawing = true;
        new Thread(this).start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mIsDrawing = false;
    }

    @Override
    public void run() {
        long start = System.currentTimeMillis();
        while (mIsDrawing) {
            draw();
            long end = System.currentTimeMillis();
            if (end - start < 100) {
                try {
                    Thread.sleep(100 - end + start);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void draw() {
        try {
            //鎖定畫布并返回畫布對象
            mCanvas = mHolder.lockCanvas();
            //接下去就是在畫布上進行一下draw
            mCanvas.drawColor(Color.WHITE);
            mCanvas.drawPath(mPath, mPaint);
        } catch (Exception e) {
        } finally {
            //當畫布內(nèi)容不為空時,才post淹父,避免出現(xiàn)黑屏的情況株婴。
            if (mCanvas != null)
                mHolder.unlockCanvasAndPost(mCanvas);
        }
    }

    /**
     * 繪制觸摸滑動路徑
     *
     * @param event MotionEvent
     * @return true
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                Log.d(TAG, "onTouchEvent: down");
                mPath.moveTo(x, y);
                break;
            case MotionEvent.ACTION_MOVE:
                Log.d(TAG, "onTouchEvent: move");
                mPath.lineTo(x, y);
                break;
            case MotionEvent.ACTION_UP:
                Log.d(TAG, "onTouchEvent: up");
                break;
        }
        return true;
    }

    /**
     * 清屏
     *
     * @return true
     */
    public boolean reDraw() {
        mPath.reset();
        return true;
    }
}
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子困介,更是在濱河造成了極大的恐慌大审,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件座哩,死亡現(xiàn)場離奇詭異徒扶,居然都是意外死亡,警方通過查閱死者的電腦和手機根穷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門姜骡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人屿良,你說我怎么就攤上這事圈澈。” “怎么了管引?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵士败,是天一觀的道長。 經(jīng)常有香客問我褥伴,道長谅将,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任重慢,我火速辦了婚禮饥臂,結果婚禮上,老公的妹妹穿的比我還像新娘似踱。我一直安慰自己隅熙,他們只是感情好,可當我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布核芽。 她就那樣靜靜地躺著囚戚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪轧简。 梳的紋絲不亂的頭發(fā)上驰坊,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天,我揣著相機與錄音哮独,去河邊找鬼拳芙。 笑死,一個胖子當著我的面吹牛皮璧,可吹牛的內(nèi)容都是我干的舟扎。 我是一名探鬼主播,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼悴务,長吁一口氣:“原來是場噩夢啊……” “哼睹限!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤邦泄,失蹤者是張志新(化名)和其女友劉穎删窒,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體顺囊,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡肌索,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了特碳。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诚亚。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖午乓,靈堂內(nèi)的尸體忽然破棺而出站宗,到底是詐尸還是另有隱情,我是刑警寧澤益愈,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布梢灭,位于F島的核電站,受9級特大地震影響蒸其,放射性物質發(fā)生泄漏敏释。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一摸袁、第九天 我趴在偏房一處隱蔽的房頂上張望钥顽。 院中可真熱鬧,春花似錦靠汁、人聲如沸蜂大。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽奶浦。三九已至,卻和暖如春踢星,著一層夾襖步出監(jiān)牢的瞬間澳叉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工斩狱, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留耳高,地道東北人扎瓶。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓所踊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親概荷。 傳聞我的和親對象是個殘疾皇子秕岛,可洞房花燭夜當晚...
    茶點故事閱讀 44,629評論 2 354

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