Android應用之SurfaceView的雙緩衝使用

來源:互聯網
上載者:User

發布: | 作者: | 來源:
menglongfei | 查看:958次 | 使用者關註:

這次介紹SurfaceView的雙緩衝使用。雙緩衝是為了防止動畫閃爍而實現的一種多線程應用,基於SurfaceView的雙緩衝實現很簡單,開一條線程並在其中繪圖即可。本文介紹基於SurfaceView的雙緩衝實現,以及介紹類似的更高效的實現方法。 本文程式運行如下,左邊是開單個線程讀取並繪圖,右邊是開兩個線程,一個專門讀取圖片,一個專門繪圖:對比一下,右邊動畫的幀速明顯比左邊的快,左右兩者都沒使用Thread.sleep()。為什麼要開兩個

這次介紹SurfaceView的雙緩衝使用。雙緩衝是為了防止動畫閃爍而實現的一種多線程應用,基於SurfaceView的雙緩衝實現很簡單,開一條線程並在其中繪圖即可。本文介紹基於SurfaceView的雙緩衝實現,以及介紹類似的更高效的實現方法。

        本文程式運行如下,左邊是開單個線程讀取並繪圖,右邊是開兩個線程,一個專門讀取圖片,一個專門繪圖:

對比一下,右邊動畫的幀速明顯比左邊的快,左右兩者都沒使用Thread.sleep()。為什麼要開兩個線程一個讀一個畫,而不去開兩個線程像左邊那樣都“邊讀邊畫”呢?因為SurfaceView每次繪圖都會鎖定Canvas,也就是說同一片地區這次沒畫完下次就不能畫,因此要提高雙緩衝的效率,就得開一條線程專門畫圖,開另外一條線程做預先處理的工作。

main.xml的源碼:

view plaincopy to clipboardprint?

    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:orientation="vertical">

            android:layout_width="wrap_content" android:layout_height="wrap_content">

                  android:layout_height="wrap_content" android:text="單個獨立線程">

                  android:layout_height="wrap_content" android:text="兩個獨立線程">

    
            android:layout_width="fill_parent" android:layout_height="fill_parent">

android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical">

  android:layout_width="wrap_content" android:layout_height="wrap_content">
    android:layout_height="wrap_content" android:text="單個獨立線程">
    android:layout_height="wrap_content" android:text="兩個獨立線程">

  android:layout_width="fill_parent" android:layout_height="fill_parent">

本文程式的源碼:

view plaincopy to clipboardprint?
package com.testSurfaceView; 

import java.lang.reflect.Field; 
import java.util.ArrayList; 
import android.app.Activity; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Canvas; 
import android.graphics.Paint; 
import android.graphics.Rect; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.View; 
import android.widget.Button; 

public class testSurfaceView extends Activity { 
    /** Called when the activity is first created. */
    Button btnSingleThread, btnDoubleThread; 
    SurfaceView sfv; 
    SurfaceHolder sfh; 
    ArrayList imgList = new ArrayList(); 
    int imgWidth, imgHeight; 
    Bitmap bitmap;//獨立線程讀取,獨立線程繪圖 

    @Override
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 

        btnSingleThread = (Button) this.findViewById(R.id.Button01); 
        btnDoubleThread = (Button) this.findViewById(R.id.Button02); 
        btnSingleThread.setOnClickListener(new ClickEvent()); 
        btnDoubleThread.setOnClickListener(new ClickEvent()); 
        sfv = (SurfaceView) this.findViewById(R.id.SurfaceView01); 
        sfh = sfv.getHolder(); 
        sfh.addCallback(new MyCallBack());// 自動運行surfaceCreated以及surfaceChanged 
    } 

    class ClickEvent implements View.OnClickListener { 

        @Override
        public void onClick(View v) { 

            if (v == btnSingleThread) { 
                new Load_DrawImage(0, 0).start();//開一條線程讀取並繪圖 
            } else if (v == btnDoubleThread) { 
                new LoadImage().start();//開一條線程讀取 
                new DrawImage(imgWidth + 10, 0).start();//開一條線程繪圖 
            } 

        } 

    } 

    class MyCallBack implements SurfaceHolder.Callback { 

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, 
                int height) { 
            Log.i("Surface:", "Change"); 

        } 

        @Override
        public void surfaceCreated(SurfaceHolder holder) { 
            Log.i("Surface:", "Create"); 

            // 用反射機制來擷取資源中的圖片ID和尺寸 
            Field[] fields = R.drawable.class.getDeclaredFields(); 
            for (Field field : fields) { 
                if (!"icon".equals(field.getName()))// 除了icon之外的圖片 
                { 
                    int index = 0; 
                    try { 
                        index = field.getInt(R.drawable.class); 
                    } catch (IllegalArgumentException e) { 
                        // TODO Auto-generated catch block 
                        e.printStackTrace(); 
                    } catch (IllegalAccessException e) { 
                        // TODO Auto-generated catch block 
                        e.printStackTrace(); 
                    } 
                    // 儲存圖片ID 
                    imgList.add(index); 
                } 
            } 
            // 取得映像大小 
            Bitmap bmImg = BitmapFactory.decodeResource(getResources(), 
                    imgList.get(0)); 
            imgWidth = bmImg.getWidth(); 
            imgHeight = bmImg.getHeight(); 
        } 

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) { 
            Log.i("Surface:", "Destroy"); 

        } 

    } 

    /*
     * 讀取並顯示圖片的線程
     */
    class Load_DrawImage extends Thread { 
        int x, y; 
        int imgIndex = 0; 

        public Load_DrawImage(int x, int y) { 
            this.x = x; 
            this.y = y; 
        } 

        public void run() { 
            while (true) { 
                Canvas c = sfh.lockCanvas(new Rect(this.x, this.y, this.x 
                        + imgWidth, this.y + imgHeight)); 
                Bitmap bmImg = BitmapFactory.decodeResource(getResources(), 
                        imgList.get(imgIndex)); 
                c.drawBitmap(bmImg, this.x, this.y, new Paint()); 
                imgIndex++; 
                if (imgIndex == imgList.size()) 
                    imgIndex = 0; 

                sfh.unlockCanvasAndPost(c);// 更新螢幕顯示內容 
            } 
        } 
    }; 

    /*
     * 只負責繪圖的線程
     */
    class DrawImage extends Thread { 
        int x, y; 

        public DrawImage(int x, int y) { 
            this.x = x; 
            this.y = y; 
        } 

        public void run() { 
            while (true) { 
                if (bitmap != null) {//如果映像有效 
                    Canvas c = sfh.lockCanvas(new Rect(this.x, this.y, this.x 
                            + imgWidth, this.y + imgHeight)); 

                    c.drawBitmap(bitmap, this.x, this.y, new Paint()); 

                    sfh.unlockCanvasAndPost(c);// 更新螢幕顯示內容 
                } 
            } 
        } 
    }; 

    /*
     * 只負責讀取圖片的線程
     */
    class LoadImage extends Thread { 
        int imgIndex = 0; 

        public void run() { 
            while (true) { 
                bitmap = BitmapFactory.decodeResource(getResources(), 
                        imgList.get(imgIndex)); 
                imgIndex++; 
                if (imgIndex == imgList.size())//如果到盡頭則重新讀取 
                    imgIndex = 0; 
            } 
        } 
    }; 
}

 

from:http://www.hqew.com/tech/doc/135410.html

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.