Android顯示系統之View與SurfaceView更新螢幕的區別
/********************************************************************************************
* author:[email protected]大鐘
* E-mail:[email protected]
*
* 注:本文為原創,僅作為學習交流使用,轉載請標明作者及出處。
********************************************************************************************/
1、View
Viewextends Objectimplements Drawable.Callback KeyEvent.Callback AccessibilityEventSource Class OverviewThis 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 View類為使用者介面提供了最基礎的元件,View類元件負責更換螢幕與處理事件。同時,View類也是widgets類的基礎類,widgets類可以建立基礎的UI元件,如Bottons、Textview等等。View類的其中一個直接子類ViewGroup是layous的基礎類,layous是用來裝載View或者其他的ViewGrous的,並且可以定義這些裝載內容的特性。 |
2、
從上述的Overview可知,SurfaceView是繼承於View類的,(GLSurfaceView是繼承於SurfaceView的)。關於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: [email protected]
* 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, 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.
如下面的程式碼所示。這樣的話,就不必擔心主UI執行緒被堵塞了。
/*
* author: conowen
* e-mail: [email protected]
* 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);
}
}
相關推薦
Android顯示系統之View與SurfaceView更新螢幕的區別
/******************************************************************************************** * author:[email protected]大鐘
Android圖形系統之Surface、SurfaceView、SurfaceHolder及SurfaceHolder.Callback之間的聯絡
SurfaceHolder 結構 繼承關係 public interface SurfaceHolder android.view.SurfaceHolder 概述 抽象介面持有人顯示錶面。允許您控制面的大小和格式
Android 多媒體應用:視訊播放之VideoView與SurfaceView
實際上我們這裡所說的VideoView與SurfaceView並不適用於我們真正的實際開發中,那麼我們為什麼還要學習他們呢?在實際開發中我們又該如何使用什麼呢? 一、為什麼要學習VideoView與SurfaceView 在思考為什麼學習VideoV
【Android開發】之Fragment與Acitvity通信
對象 p s ets roi mit blog () open findview 上一篇我們講到與Fragment有關的經常使用函數,既然Fragment被稱為是“小Activity”。如今我們來講一下Fragment怎樣與Acitivity通信。
MVC初級知識之——View與Controller的講解
str 寫入 開發 content login 結果 執行 母版 rect Controller是MVC中比較重要的一部分。幾乎所有的業務邏輯都是在這裏進行處理的,並且從Model中取出數據。在ASP.NET MVC Preview5中,將原來的Controlle
Android進階之Fragment與Activity之間的數據交互
|| int tails support 實例 onclick interface rod sel 1 為什麽 因為Fragment和Activity一樣是具有生命周期,不是一般的bean通過構造函數傳值,會造成異常。 2 Activity把值傳遞給Fragment 2.1
Android 7.0 之拍照與圖片裁剪適配
在Android 7.0以上,在相機拍照和圖片裁剪上,可能會碰到以下一些錯誤: Process: com.yuyh.imgsel, PID: 22995 // 錯誤1 android.os.FileUriExposedException: file:///storage/emulate
android Gui系統之SurfaceFlinger(5)---Vsync(2)
9.Vsync第二部分 在上一篇中我們講到,檢視的重新整理需要很多步驟, void SurfaceFlinger::handleMessageRefresh() { ATRACE_CALL(); preComposition(); //合成前的準備 rebui
android Gui系統之SurfaceFlinger(4)---Vsync(1)
8.Vsync 回到頂部 8.1概論 VSYNC(Vertical Synchronization)是一個相當古老的概念,對於遊戲玩家,它有一個更加大名鼎鼎的中文名字—-垂直同步。 “垂直同步(vsync)”指的是顯示卡的輸出幀數和螢幕的垂直重新整理率相同,這完全是一個CRT顯示器上
android Gui系統之SurfaceFlinger(3)---SurfaceFlinger
7.SurfaceFlinger SurfaceFlinger在前面的篇幅了,多有涉及。 SurfaceFlinger是GUI重新整理UI的核心,所以任何關於SurfaceFlinger的改進都會對android UI系統有重大影響。 SurfaceFlinger主要分為4個部分 1
android Gui系統之SurfaceFlinger(2)---BufferQueue
6 BufferQueue 上一篇已經說到,BufferQueue是SurfaceFlinger管理和消費surface的中介,我們就開始分析bufferqueue。 每個應用 可以由幾個BufferQueue? 應用繪製UI 所需的記憶體從何而來? 應用和SurfaceFlinge
android Gui系統之SurfaceFlinger(1)---SurfaceFlinger概論
GUI 是任何系統都很重要的一塊。 android GUI大體分為4大塊。 1)SurfaceFlinger 2)WMS 3)View機制 4)InputMethod 這塊內容非常之多,但是理解後,可以觸類旁通,其實現在主流的系統,包括andorid,ios
Linux檔案系統之使用者與組管理
目錄 ①使用者與組管理之重要檔案 (1)/etc/passwd (2)/etc/shadow (3)/etc/login.defs (4)/etc/skel (目錄) (5)/etc/de
Android學習筆記之View的事件分發機制
一、點選事件的傳遞規則 所謂的點選事件分發過程,其實就是當我們點選螢幕,產生了一個MotionEvent之後,系統將這個事件傳遞給一個具體View的過程。總的來說,事件總是先傳遞給Activity,然後傳遞給Window,再傳遞給頂級View(Activity→Window
android Gui系統之SurfaceFlinger(1)---SurfaceFlinger概論【轉】
轉自:https://www.cnblogs.com/deman/p/5584198.html 閱讀目錄 1.OpenGL & OpenGL ES 2.Android的硬體介面HAL 3.Android顯示裝置:Gralloc & FrameBuff
學生管理系統之ODBC與SQL的配置連線
雖然前幾天就一直在進行學生系統專案,但是在一開始的資料庫連結ODBC上就出現了問題,但是在今天半個小時的努力下,中功夫不負有心人完成了目標。下面是我登陸不成功出現的問題 出現這個問題的原因 SQL Server 相關連結的和密碼不匹配 解決方法如下: 首先,開啟
Android進階之View.inflate和LayoutInflater.inflate方法區別
1 LayoutInflater用於載入佈局 LayoutInflater用於載入佈局的。載入佈局的任務通常都是在Activity中呼叫setContentView()方法來完成的。其實setContentView()方法的內部也是使用LayoutInflater來載入佈局的,只不過
Android ListView優化之區域性重新整理(更新)(非notifyDataSetChanged)
在Android開發中我們經常會用到listview的資料和介面重新整理動作,我們每次可能會用到的都是Adapter.notifyDataSetChanged()方法。這個方法的原理是利用觀察者模式對我們的資料來源進行監聽,當我們的資料來源發生變化
Android顯示系統中VSYNC簡介
Android系統中關於VSYNC的簡介 92HWComposer::HWComposer( 93 const sp<SurfaceFlinger>&flinger, 94 EventHandler& handler)
Android雙系統之基本問題研究
序:近年來Android智慧手機已成為人們生活的一部分,隨著Android手機功能的日益豐富,它正在改變不少行業的辦公模式。尤其是在警察、海關、銀行等行業,移動辦公顯得尤為迫切。如通過手機接入專有網路