求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
  
 
 
     
   
分享到
Android显示系统之View与SurfaceView更新屏幕的区别
 

作者:conowen,发布于2012-9-10,来源:博客

 

1、View

View

extends Object

implements Drawable.Callback KeyEvent.Callback AccessibilityEventSource

java.lang.Object

android.view.View

  • Known Direct Subclasses(直接子类,SurfaceView是View的子类)

AnalogClock,ImageView,KeyboardView,MediaRouteButton,ProgressBar,Space,SurfaceView,TextView,TextureView,ViewGroup,ViewStu

  • Known Indirect Subclasses(间接子类)

AbsListView,AbsSeekBar,AbsSpinner,AbsoluteLayout,AdapterView<T extends Adapter>,AdapterViewAnimator,AdapterViewFlipper,AppWidgetHostView,AutoCompleteTextView, Button, CalendarView, CheckBox, CheckedTextView, Chronometer, and 53 others.

Class Overview

This class represents the basic building block for user interface components. A View occupies a rectangular area on the screen and is responsible for drawing and event handling. View is the base class forwidgets, which are used to create interactive UI components (buttons, text fields, etc.). TheViewGroup subclass is the base class forlayouts, which are invisible containers that hold other Views (or other ViewGroups) and define their layout properties.

View类为用户界面提供了最基础的组件,View类组件负责更换屏幕与处理事件。同时,View类也是widgets类的基础类,widgets类可以创建基础的UI组件,如Bottons、Textview等等。View类的其中一个直接子类ViewGroup是layous的基础类,layous是用来装载View或者其他的ViewGrous的,并且可以定义这些装载内容的特性。

2、 从上述的Overview可知,SurfaceView是继承于View类的,(GLSurfaceView是继承于SurfaceView的)。

Android更新屏幕主要有两种方式,继承SurfaceView实现SurfaceHolder.callback接口来实现屏幕的更新。

或者直接继承View类,复写OnDraw方法实现更新屏幕。

事实上,两种是用本质的区别的。

3、View与SurfaceView更新屏幕的区别

对于SurfaceView更新屏幕,是在非UI线程(主线程)中更新的。而对于View,则是在UI的主线程中更新画面。

那在UI的主线程中更新画面很容易造成主线程的堵塞,造成程序的长时间无响应,当主UI线程超过5秒钟没有响应用户的操作,Android系统会提示是否关闭应用程序。

当使用SurfaceView 来更新画面的话,就不必担心堵塞主UI线程这个问题了。但是这也带来了另外一个问题,线程的同步性。

所以当更新操作说花的时间较长,而且数据量较大的话,一般采用SurfaceView方式更新屏幕,而少用View。

4、Demo程序

/*
 * author: conowen
 * e-mail: conowen@hotmail.com
 * date  :  2012.8.8
 */
package com.conowen.viewtestdemo;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.view.View;

public class MyView extends View {

	private int counter;

	public MyView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}

	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.onDraw(canvas);
/*		synchronized (this) {
			try {
				wait(10 * 1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
*/
		// 设定Canvas对象的背景颜色
		canvas.drawColor(Color.YELLOW - counter);

		// 创建画笔
		Paint p = new Paint();
		// 设置画笔颜色
		p.setColor(Color.RED);
		// 设置文字大小
		p.setTextSize(40);
		// 消除锯齿
		p.setFlags(Paint.ANTI_ALIAS_FLAG);

		// 在canvas上绘制rect
		canvas.drawArc(new RectF(100, 50, 400, 350), 0, counter, true, p);
		if (counter == 400) {
			counter = 0;
		}

		canvas.drawText("counter = " + (counter++), 500, 200, p);
		// 重绘, 再一次执行onDraw 程序
		invalidate();

	}

}

效果图:

打开下面的代码,测试堵塞主UI线程(长按屏幕5秒以上)就会出现如下的图。

synchronized (this) {
			try {
				wait(10 * 1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

注意:

onDraw方法是运行于主UI线程中的,如果你在onDraw中执行invalidate()方法去更新屏幕,是可以的。但是你既要继承View而且要不希望堵塞主UI线程的话,可以另外新建线程,然后在线程中执行postInvalidate()方法去更新屏幕。也就是说invalidate()方法只能在主UI线程中被调用,postInvalidate()方法只能在非主UI线程中被调用。否则会出现如下error

08-08 15:33:34.587: E/AndroidRuntime(4995): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

这两个方法只是再次调用onDraw方法而已。

Invalidate the whole view. If the view is visible, onDraw(android.graphics.Canvas) will be called at some point in the future. This must be called from a UI thread. To call from a non-UI thread, call postInvalidate().

如下面的代码所示。这样的话,就不必担心主UI线程被堵塞了。

/*
 * author: conowen
 * e-mail: conowen@hotmail.com
 * date  :  2012.8.4
 */
package com.conowen.viewtestdemo;

import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.view.View;

public class MyView extends View {

    private int counter;
    private boolean isNewThread;
    private RectF rectf;
    private Paint p;
    private Timer timer;

    public MyView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        isNewThread = true;
        rectf = new RectF(100, 50, 400, 350);
        p = new Paint();
        timer = new Timer();
    }

    public void newThread() {

        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                postInvalidate();
                
            }
        }, 0, 100);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);
        if (isNewThread) {
            newThread();
            isNewThread = false;
        }
        // 设定Canvas对象的背景颜色
        canvas.drawColor(Color.YELLOW - counter);

        // 设置画笔颜色
        p.setColor(Color.RED);
        // 设置文字大小
        p.setTextSize(40);
        // 消除锯齿
        p.setFlags(Paint.ANTI_ALIAS_FLAG);

        // 在canvas上绘制rect
        canvas.drawArc(rectf, 0, counter, true, p);
        if (counter == 400) {
            counter = 0;
        }

        canvas.drawText("counter = " + (counter++), 500, 200, p);

    }

} 

相关文章

深度解析:清理烂代码
如何编写出拥抱变化的代码
重构-使代码更简洁优美
团队项目开发"编码规范"系列文章
相关文档

重构-改善既有代码的设计
软件重构v2
代码整洁之道
高质量编程规范
相关课程

基于HTML5客户端、Web端的应用开发
HTML 5+CSS 开发
嵌入式C高质量编程
C++高级编程

 
分享到
 
 
     


android人机界面指南
Android手机开发(一)
Android手机开发(二)
Android手机开发(三)
Android手机开发(四)
iPhone消息推送机制实现探讨
手机软件测试用例设计实践
手机客户端UI测试分析
手机软件自动化测试研究报告
更多...   


Android高级移动应用程序
Android应用开发
Android系统开发
手机软件测试
嵌入式软件测试
Android软、硬、云整合


领先IT公司 android开发平台最佳实践
北京 Android开发技术进阶
某新能源领域企业 Android开发技术
某航天公司 Android、IOS应用软件开发
阿尔卡特 Linux内核驱动
艾默生 嵌入式软件架构设计
西门子 嵌入式架构设计
更多...