将以Adobe SVG Viewer提供的属性和方法为准,因为不同解析器对JavaScript以及相关的属性和方法支持的程度不同,有些方法和属性是某个解析器所特有的。SVG支持DOM2标准。
12.2.1 文档初始化相关— evt属性
evt表示事件本身,可以通过evt获取与当前事件相关的信息,用户可以在script中定义响应函数,进行相应的处理。它与普通JavaScript脚本中的event基本相同,只不过在普通JavaScript的脚本中简写成“e”。
— ownerDocument属性
通过引用该属性获得当前SVG文件的文档对象,也就是得到SVG的DOM结构。
使用举例:svgdoc = evt.target.ownerDocument
— getOwnerDocument()方法
通过调用该方法获得当前SVG文件的文档对象,也就是得到SVG的DOM结构。
使用举例:svgdoc = evt.target.getOwnerDocument()
— target属性
通过引用该属性获得事件产生于哪个SVG元素,有时可能是该元素的父元素。
使用举例:object = evt.target
— getTarget()方法
通过调用该方法获得事件产生于哪个SVG元素,有时可能是该元素的父元素。
使用举例:object = evt.getTarget()
例程12-1 获得SVG文档对象
<svg width="640" height="480" onload="init(evt)"> u
<script><![CDATA[
function init(evt)
{
svgDoc = evt.target.ownerDocument; v
svgRoot = svgDoc.rootElement;
alert(svgRoot.nodeName);
}
]]></script>
<rect x="100" y="100" width="100" height="50" fill="red" stroke-width= "2"/>
</svg>
该例展示了如何在SVG文档被载入后,调用初始化程序,以获得SVG的DOM结构,为后续的编程做好准备。
例程12-1中,u 处表示在SVG文档载入时激活的“onload”事件中执行“init”函数;“init”函数先是得到SVG Document对象,然后获得该对象的根元素(也就是“SVG”元素),最后的效果是弹出一个消息框,上面显示“SVG”。
v 处的代码可以替换为“svgDoc = evt.getTarget().getOwnerDocument;”,得到的效果是一样的。
12.2.2 DOM对象操作相关前面我们已经介绍过,DOM对象是一个树型的结构,并且经过载入后就放在内存中供我们读写。如何对这棵树进行操作,也就成为发挥SVG交互性很关键的一步。下面所示的方法中,有些是文档对象(Document)的方法,有些是文档元素(Element)的方法,需要区别开来。DOM可以分为三大部分:文档基本元素、文档对象和各种类型的从文档基本元素派生出的文档元素。文档对象是文档对象模型的顶级对象,它包含了整个文档的内容。各种类型的文档元素派生自文档基本元素类型,用于描述文档中各种实际存在的元素。其中可以定义一种文档元素,它们可以容纳其他的文档元素,这些元素就是容器元素,实际上文档对象就是最大的容器元素。由于文档对象模型中存在容器元素,因此所有的对象都组成一个树状结构,称为文档对象树或者DOM树,其中根节点就是文档对象。
— getElementById(ID_Name)方法
通过元素的ID名获得该元素。
使用举例:object = svgdoc.getElementById("map")
— getElementsByTagName(Tag_Name)方法
通过元素名获得一个或者一组元素,注意方法名中的“Elements”是复数,说明返回的元素可能有多个,是一个“NodeList”。
使用举例:object = svgdoc.getElementsByTagName ("rect")
例程12-2 获得SVG文档中的元素
<svg width="640" height="480" onload="init(evt)">
<script><![CDATA[
function init(evt)
{
svgDoc = evt.target.ownerDocument;
svgRoot = svgDoc.rootElement;
rect = svgRoot.getElementById("rect1");u
rects = svgRoot.getElementsByTagName("rect");v
alert(rect+","+rects);
}
]]></script>
<rect id="rect1" x="100" y="100" width="100" height="50" fill="red"/>
<rect id="rect2" x="100" y="200" width="100" height="50" fill="red"/>
<rect id="rect3" x="100" y="300" width="100" height="50" fill="red"/>
</svg>
打开该文档后,弹出的消息框上显示“[object SVGRectElement],[object NodeList]”。
例程12-2中,u处使用“rect1”的ID名得到了“svgRoot”下属的一个矩形元素(SVGRectElement)。v是为了获得所有“svgRoot”下属的“<rect>”元素,返回的是一个“NodeList”,本例中一共有三个符合条件的元素。
— getAttribute(ID_Name)方法
根据所提供的ID名来获得元素的属性值。
使用举例:color = node.getAttribute ("fill")
— setAttribute(Attribute_Name,Value)方法
设置该元素属性名为“Attribute_Name”的,属性的值为“Value”。
使用举例:color = node.getAttribute ("fill")
— setAttributeNS(NameSpace, Attribute_Name ,Value)方法
功能效果同setAttribute方法,区别就是增加了为属性名加上命名空间(NameSpace)。在ASV3.0中,属性名都是默认SVG的命名空间,所以不需要再特别注明,但是如果你要使用“xlink”中的属性,就要加入相应的命名空间“http://www.w3.org/2000 /xlink/namespace/”。
使用举例:object = svgdoc.setAttributeNS ("http://www.w3.org/2000/xlink/namespace/", xlink:href, "index.html")
注意 绝对不要在同一个程序中混合使用DOM1非名称空间API和DOM2名称空间感知的API(例如,createElement和createElementNS)。如果使用名称空间,请尽量在根元素位置声明所有名称空间,并且不要覆盖名称空间前缀,否则情况会非常混乱。一般来说,只要按照惯例,就不会触发使你陷入麻烦的临界情况。
例程12-3 设置SVG元素的属性
<svg width="640" height="480" onload="init(evt)">
<script><![CDATA[
function init(evt)
{
svgDoc = evt.target.ownerDocument;
svgRoot = svgDoc.rootElement;
rect1 = svgRoot.getElementById("rect1");
rect2 = svgRoot.getElementById("rect2");
}
function setSvgAttribute(evt,flag)
{
if ( flag == 1)
rect1.setAttribute("fill", "green");u
else
{
rect2.setAttributeNS(null, "fill", "green");v
}
}
function getSvgAttribute(evt)
{
alert(rect1.getAttribute("fill")+ "," + rect1.getAttribute("height"));w
}
]]></script>
<rect id="rect1" x="100" y="100" width="100" height="50" fill="red" onclick="getSvgAttribute(evt)" onmousemove="setSvgAttribute(evt,1) "/><rect id="rect2" x="100" y="200" width="100" height="50" fill="red" onclick="setSvgAttribute(evt,2)"/>
</svg>
这里例子中我们接触到了SVG中的事件,这跟HTML中的事件很相似,关于SVG的事件我们会在后面的章节中做详细介绍。这里用到了两个事件:一个是鼠标单击事件“onclick”,一个是鼠标移动到“<rect>”时触发的“onmousemove”事件,,注意它们的大小写,全部是小写,否则事件无法激活,浏览器会报告脚本错误。
我们想要实现的效果是,单击ID为“rect1”的矩形时,能得到它的填充颜色值和矩形的高度值,并且鼠标移动到该矩形的时候,矩形的填充颜色从红色变成绿色;另外一个矩形,我们在单击它的时候,它的填充颜色从红色变成绿色。
例程12-3中,u处设置矩形“rect1”的“fill”属性为“green”;。
v通过命名空间来设置属性值。不过命名空间参数的值是“null”,因为ASV3.0已经内置了命名空间,所以你再给这些SVG的属性添加命名空间的话就会出错,所以填入“null”值。
w是为了弹出消息框,显示我们需要知道的那两个属性值。
— createElement(Element_Type)方法
在DOM对象内创建一个新的元素,可以指定创建哪一种类型的元素,并且返回对这个新元素的引用。
使用举例:newnode = svgdoc.createElement("rect")
— appendChild(Element)方法
在该元素的最后追加一个孩子节点。
使用举例:someElement.appendChild(node)
例程12-4 动态创建SVG的元素
<svg width="640" height="480" onload="init(evt)">
<script><
在重写View的时候,会遇到这两个方法
protected void onAttachedToWindow()
Description copied from class: View
This is called when the view is attached to a window. At this point it has a Surface and will start drawing. Note that this function is guaranteed to be called before View.onDraw(android.graphics.Canvas), however it may be called
any time before the first onDraw -- including before or after View.onMeasure(int, int).
Overrides:
onAttachedToWindow in class View
当此view附加到窗体上时调用该方法。在这时,view有了一个用于显示的Surface,将开始绘制。注意,此方法要保证在调用onDraw(Canvas) 之前调用,但可能在调用 onDraw(Canvas) 之前的任何时刻,包括调用 onMeasure(int, int) 之前或之后。
看得出次方法在onDraw方法之前调用,也就是view还没有画出来的时候,可以在此方法中去执行一些初始化的操作,google的AlarmClock动态时钟View就是在这个方法中进行广播的注册,代码如下:
@Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (Log.LOGV) Log.v("onAttachedToWindow " + this); if (mAttached) return; mAttached = true; if (mAnimate) { setBackgroundResource(R.drawable.animate_circle); /* Start the animation (looped playback by default). */ ((AnimationDrawable) getBackground()).start(); } if (mLive) { /* monitor time ticks, time changed, timezone */ IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_TIME_TICK); filter.addAction(Intent.ACTION_TIME_CHANGED); filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); mContext.registerReceiver(mIntentReceiver, filter, null, mHandler); } /* monitor 12/24-hour display preference */ mFormatChangeObserver = new FormatChangeObserver(); mContext.getContentResolver().registerContentObserver( Settings.System.CONTENT_URI, true, mFormatChangeObserver); updateTime(); }
另外在屏蔽Home键的时候也会用到
public void onAttachedToWindow() { this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD); super.onAttachedToWindow(); }
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
protected void onDetachedFromWindow()
Description copied from class: View
This is called when the view is detached from a window. At this point it no longer has a surface for drawing.
Overrides:
onDetachedFromWindow in class AdapterView<ListAdapter>
将视图从窗体上分离的时候调用该方法。这时视图已经不具有可绘制部分。
onDetachedFromWindow()正好与onAttachedToWindow()的用法相对应,在destroy view的时候调用,所以可以加入取消广播注册等的操作,还是google的闹钟代码:
@Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (!mAttached) return; mAttached = false; Drawable background = getBackground(); if (background instanceof AnimationDrawable) { ((AnimationDrawable) background).stop(); } if (mLive) { mContext.unregisterReceiver(mIntentReceiver); } mContext.getContentResolver().unregisterContentObserver( mFormatChangeObserver); }
具体的用法视个人的需求而定了,自己控制重写就好了。
1 原则上禁止使用GC.Collect 方法
显式执行GC.Collect()有可能给内存回收增加负担,而且不一定能真正回收内存,垃圾回收周期是不确定的,由垃圾回收器引擎自动计算最佳的垃圾回收时间。在一个需要大量消耗内存的应用程序中,如果在某个确定的时间点上已经明确占用的内存不再需要,及时释放这些内存对提高应用程序的性能有显著的影响,这时就可以强制垃圾回收器执行回收周期。
GC.Collect方法强制垃圾回收器执行垃圾回收周期。在应用程序中调用GC.Collect方法可以强制垃圾回收,及时释放不再需要的大量内存。但是过于频繁的调用GC.Collect方法同样也会带来应用程序的性能问题。因为,开始执行垃圾回收线程时,垃圾回收器将挂起当前正在执行的所有线程,直到垃圾回收线程结束;另一方面,频繁的调用GC.Collect方法还将削弱垃圾回收器引擎的优化作用。而在通常情况下,垃圾回收器往往可以确定最佳的垃圾回收时间。原则上禁止使用,如果有特殊情况需要使用,要求进行代码评审
2 如果释放非托管资源,建议采用dispose模式
类实例经常封装对不受运行库管理的资源(如窗口句柄 (HWND)、数据库连接等)的控制。因此,应该既提供显式方法也提供隐式方法来释放这些资源。通过在对象上实现受保护的Finalize 方法(在 C#中为析构函数语法)可提供隐式控制。当不再有任何有效的对象引用后,垃圾回收器在某个时间调用此方法。
在有些情况下,可能想为使用该对象的程序员提供显式释放这些外部资源的能力,以便在垃圾回收器释放该对象之前释放这些资源。当外部资源稀少或者昂贵时,如果程序员在资源不再使用时显式释放它们,则可以获得更好的性能。若要提供显式控制,请实现由IDisposable接口提供的Dispose方法。在完成使用该对象的操作时,该对象的使用者应调用此方法。即使对对象的其他引用是活动的,也可以调用Dispose。
正例:
//基类模式.
public class Base: IDisposable
{
//实现 Idisposable接口.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
//其他状态 (托管 objects).
}
//释放状态 (非托管对象)
}
// 用 C# 析构函数来负责 finalization 的代码
~Base()
{
Dispose (false);
}
}
//子类模式.
public class Derived: Base
{
protected override void Dispose(bool disposing)
{
if (disposing)
{
//释放托管资源.
}
//释放非托管资源
//调用基类的Dispose方法
base.Dispose(disposing);
}
//子类不需要Finalize方法或者无参数的Dispose方法,因为它从基类继承了
}
3 如果有IO操作,建议使用Buffer缓冲区
说明:在IO操作时,输入输出流实际的长度未知的情况下,比如:网络流。可以先初始化一段缓存,再将流读出来的流信息写到内存流里面,这样可以提高性能并且安全
正例:
publicstaticbyte[] ReadFully(Stream stream)
{ //初始化一个8k的缓存
byte[] buffer = new byte[8192];
using ( MemoryStream ms = new MemoryStream() )
{
//返回结果后会自动回收调用该对象的Dispose方法释放内存
while ( true )
{
int read = stream.Read(buffer, 0, buffer.Len