As we all know, view is redrawn by refreshing. Android system redraws the screen by sending VSYNC signals. The refresh interval is 16 Ms. If the view completes all the operations you need within 16 ms, the user will not have the sense of carton visually; and if the operation logic is too much, Especially if the interface needs to be refreshed frequently, the main thread will be blocked continuously, which will lead to picture jamming.
So Android provides a surfaceView.
1.View is mainly suitable for active updates, while surfaceView is mainly suitable for passive updates, such as frequent refreshes.
2.View refreshes the View in the main thread, and surfaceView usually refreshes the page with a sub-thread.
3.View has no double buffering mechanism in drawing, while surfaceView has already implemented double buffering mechanism in the bottom layer.
So if customized views need frequent refreshes or have a large amount of data processing when refreshing, then you can consider using surfaceView instead of View.
There is a set of templates using Surface View. Here is an example to illustrate how to use Surface View to make oscilloscope effect and draw sinusoidal wave.
package com.example.tangzh.MyView; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import android.view.SurfaceHolder; import android.view.SurfaceView; import com.example.tangzh.mylearn.R; /** * Created by TangZH on 2017/4/30. */ public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable //Inheritance and implementation of two interfaces { private SurfaceHolder mHolder; //Used for drawing. Canvas private Canvas mCanvas; //Subthread flags private boolean mIsDrawing; //Paint brush private Paint mPaint; private Path mPath; //x coordinate private int x=0; //y coordinate private int y=400; public MySurfaceView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(); } public MySurfaceView(Context context) { super(context); initView(); } public MySurfaceView(Context context, AttributeSet attrs) { super(context, attrs); initView(); } private void initView() { mHolder=getHolder(); mHolder.addCallback(this); setFocusable(true); setFocusableInTouchMode(true); this.setKeepScreenOn(true); } @Override public void surfaceCreated(SurfaceHolder surfaceHolder) { mIsDrawing=true; mPath=new Path(); mPath.moveTo(0,400); mPaint=new Paint(); mPaint.setColor(getResources().getColor(R.color.colorTheme)); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(5); new Thread(this).start(); } @Override public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) { } @Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) { mIsDrawing=false; } @Override public void run() { while (mIsDrawing) { draw(); x+=5; y=(int)(100* Math.sin(x*2*Math.PI/180)+400); mPath.lineTo(x,y); } } private void draw() { try { mCanvas=mHolder.lockCanvas(); //SurfaceView background mCanvas.drawColor(Color.WHITE); mCanvas.drawPath(mPath,mPaint); }catch (Exception e) { e.printStackTrace(); }finally { if(mCanvas!=null) mHolder.unlockCanvasAndPost(mCanvas); //Submit canvas content } } }
Note that the current Canvas drawing object can be obtained by using the lockCanvas() method of the SurfaceView object, which is the same as the previous Canvas object, so the previous drawing operation will be retained. If you need to erase, you can clear the screen by drawing Color () method before drawing.