正常情况下神力科莎 start 退出observer怎么退出

AsyncTask、View.post(Runnable)、ViewTreeObserver三种方式总结frame animation自动启动 - Pe.潘义 - 博客园
  在一些需求中,需要在程序运行时动画自动启动,我们也知道在android提供的Tween Animation和frame animation。但是当使用frame animation时候,启动Frame Animation动画的代码anim.start();不能在OnCreate()中,因为在OnCreate()中AnimationDrawable还没有完全的与ImageView绑定,在OnCreate()中启动动画,就只能看到第一张图片。现在问题是如何才能让程序启动时自动的启动动画?可以试一下在onStart方法中,但是结果同样不能如我们所愿。这样不行,继续尝试,使用Handler试一下!代码如下:
private Runnable runnable= new Runnable() {
public void run() {
frameAnimation.start();
Handler handler=
new Handler();
//在onCreate方法中:
handler.post(runnable);&
handler对象将通过post方法,将里面的Runnable对象放到UI执行队列中,UI消费这个队列,调用Runnable的run方法。这里并不生成新的线程,此时的 Runnable 是运行在UI所在的主线程中。但是这种方法也是不行!
下面即是总结的三种自动启动frame animation的方法:
首先使用AsyncTask:Handler和AsyncTask,都是为了不阻塞主线程(UI线程),且UI的更新只能在主线程中完成,因此异步处理是不可避免的。AsyncTask使创建需要与用户界面交互的长时间运行的任务变得更简单。不需要借助线程和Handler即可实现。对于AsyncTask这里就不多说了,也就是用到一点。
imageV.setBackgroundResource(R.anim.myframeanimation);
frameAnim = (AnimationDrawable) imageV.getBackground();
class RunAnim extends AsyncTask&String, String, String&{
protected String doInBackground(String... params) {
if(!frameAnim.isRunning()){
frameAnim.stop();
frameAnim.start();
return "";
//onCreate方法中执行
RunAnim runAnim=new RunAnim();
runAnim.execute("");
这样就能在是程序自动执行frame animation了。
其次使用View.post(Runnable)的方式:
imageV.post(new Runnable(){
public void run() {
frameAnim.start();
文档:boolean android.view.&.post(&action)
Causes the Runnable to be added to the message queue. The runnable will be run on the user interface thread.即可把你的Runnable对象增加到UI线程中运行。
这样也能正常启动frame Animation。
第三就是使用ViewTreeObserver.OnPreDrawListener listener:当一个视图树将要绘制时产生事件,可以添加一个其事件处理函数:onPreDraw
OnPreDrawListener opdl=new OnPreDrawListener(){
public boolean onPreDraw() {
animDraw.start();
//onCreate方法中
imageV.getViewTreeObserver().addOnPreDrawListener(opdl);
以上即是总结的三种自动启动frame animation的方法,当然,对于android线程的处理,UI更新操作实现,肯定有其他的方法。以上描述中如有错误,还望多多包含与指教!!!
评论 - 141regression
startLoggingWithObserver IndexError
Reported by:
Milestone:
Component:
branches/logging-recursion-3289
Launchpad Bug:
Attachments (3)
(187 bytes) -
added by exarkun .
minimal reproduction of the problem
(413 bytes) -
added by glyph .
A new version of minimal.tac which opens a failsafe log to observe the traceback that the main log observer produces.
(373 bytes) -
added by glyph .
A really minimal example, which doesn't involve twistd, and just shows you the full 'maximum recursion depth exceeded' traceback.
Download all attachments as:
Comments only
Change History (16)
by exarkun
by exarkun
Attachment
by exarkun
by exarkun
exarkun added
by gtaylor
by exarkun
by exarkun
Attachment
Attachment
set to jml
set to branches/logging-recursion-3289
review added
glyph deleted
review removed
set to jml
review added
changed from jml to therve
review removed
changed from therve to jml
Resolution
set to fixed
changed from new to closed
by &automation&
jml deleted
for help on using
Download in other formats:本周热门资讯[]
软件厂商(/start.asp)&相关软件
  MP3 Observer(MP3观察员)是简单易用的 MP3 管理工具、ID3 标签编辑器、播放清单建立工具、光碟管理及 MP3 播放工具..等等。
首页 上一页 [1] 下一页 尾页
Copyright &
onlinedown.net, All rights reserved
  特聘法律顾问:、江苏德沛律师事务所刘洋律师
我们的平台: |1.1.1 摘要
        在系统的设计中,我们常常需要设计一个消息提示功能,让系统把提示信息发送到客户端。做到这一点的设计方案可以是多种多样,但是为了使系统能够易于复用,我们的设计应该遵守低耦合高内聚的设计原则,而且减少对象之间的耦合有利于系统的复用。观察者模式(Observer)是满足这一要求的各种设计方案中最重要的一种。
       使用频率
       观察者模式(Observer):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
1.1.2 正文
  
图1观察者(Observer)模式结构图
        抽象主题(Subject)角色:主题角色把所有对观察考对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,主题角色又叫做抽象被观察者(Observable)角色,一般使用一个抽象类或者一个接口实现。
       抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口叫做更新接口。抽象观察者角色一般用一个抽象类或者一个接口实现。在这个示意性的实现中,更新接口只包含一个方法(即Update()方法),这个方法叫做更新方法。
       具体主题(ConcreteSubject)角色:将有关状态存入具体现察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者角色(Concrete Observable)。具体主题角色通常用一个具体子类实现。
       具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体现察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体现察者角色可以保存一个指向具体主题对象的引用。具体观察者角色通常用一个具体子类实现。
观察者模式与推拉模式
       推模式(Push):是一种基于客户器/服务器机制,由服务器主动将信息发送到客户器的技术。
       拉模式(Pull)与推模式(Push)恰好相反,是由客户器主动向服务器发送请求的技术。
       接下来让我们通过一段示例代码介绍观察者模式(Obsever),首先假设服务器状态更新后要同时通知客户端A,B,C直接的实现如下:
/// &summary&
/// The Server class and when it updated, should notify the clients.
/// &/summary&
public class Server
/// &summary&
/// Keeps three objects referen.
/// &/summary&
/// &param name=&a&&The object of ClentA.&/param&
/// &param name=&b&&The object of ClentB.&/param&
/// &param name=&c&&The object of ClentC.&/param&
public Server(ClientA a, ClientB b, ClientC c)
public ClientA ClientA { get; set; }
public ClientB ClientB { get; set; }
public ClientC ClientC { get; set; }
public string SysMsg { get; set; }
     上面我们定义了服务器类,它包含了一个构造函数,通过它来保持ClientA,ClientB和ClientC类型对象的引用。
/// &summary&
/// The client client, it would receive message
/// when the sever updated.
/// &/summary&
public class ClientA
/// &summary&
/// Receives the message from sever.
/// &/summary&
/// &param name=&sysMsg&&&/param&
public void Notify(string sysMsg)
SysMsg = sysM
public string SysMsg { get; set; }
public class ClientB
public void Notify(string sysMsg)
SysMsg = sysM
public string SysMsg { get; set; }
public class ClientC
public void Notify(string sysMsg)
SysMsg = sysM
public string SysMsg { get; set; }
     接着我们定义了客户端类ClientA,ClientB和ClientC,由于它们是被动地接受信息(推模式),所有它们只包含接受信息的方法Notify()。
  
图2示例类图
     上图我们知道Server类保持了ClientA,ClientB和ClientC类对象的引用。
static class Program
/// &summary&
/// 应用程序的主入口点。
/// &/summary&
[STAThread]
static void Main()
var server = new Server(
new ClientA(), new ClientB(), new ClientC()) { SysMsg = &Hi everyone& };
server.ClientA.Notify(server.SysMsg);
server.ClientB.Notify(server.SysMsg);
server.ClientC.Notify(server.SysMsg);
       这里类型Server保持了ClientA,ClientB和ClientC类型的引用,但仔细考量一下如果我们要添加新的客户端类ClinetD,那么我们就需要修改Server的实现,这也意味着Server过度地依赖于客户端类,这严重地违反了面向对象设计的原则:面向接口编程,而非面向实现编程。其实ClientA,ClinetB和ClientC三个类型都有类似的功能——Notify()方法,所以我们可以为它们抽象出一个更高层的接口,通过封装变化使得我们设计依赖于抽象而非具体。
图3面向接口而非实现示例类图
       现在Server类只依赖于接口IClent,如果我们需要添加新的客户端类,只需实现IClient接口就行了,而且Server不用做出任何修改。
       现在我们对于为什么要使用观察者模式(Observer)有了初步的了解,接下来让我们通过更详细的例子介绍。
       现在我们来实现观察者模式(Observer),假设Gof电信公司要把他们最新发明的设计模式介绍给每一位Geek,他们想通过服务器把信息发送到每位Geek的移动客户端,我们很荣幸协助他们完成这一项目,OK首先我们先创建抽象接口类:IObserver,然后我们创建具体观察者:MobilePhone,Tablet和Laptop,接着创建GofTelcom作为Subject。
       首先我们定义接口IObserver,它只含一个Update()方法,由于提供了统一接口使得我们设计面对接口编程,而非面向实现编程。
/// &summary&
/// The interface of observer.
/// &/summary&
public interface IObserver
void Update(string msg);
     接着定义具体的观察者Mobile,Tablet和Laptop,它们都提供了Update()方法的具体实现。
/// &summary&
/// Concrete observer.
/// &/summary&
public class MobilePhone : IObserver
#region IObserver 成员
public void Update(string msg)
Console.WriteLine(String.Format(&I am MobilePhone.\n New message: {0}&, msg));
#endregion
/// &summary&
/// Concrete observer.
/// &/summary&
public class Tablet : IObserver
#region IObserver 成员
public void Update(string msg)
Console.WriteLine(String.Format(&OH...I am Tablet.\n New message: {0}&, msg));
#endregion
/// &summary&
/// Concrete observer.
/// &/summary&
public class Laptop : IObserver
#region Implementation of IObserver
public void Update(string msg)
Console.WriteLine(String.Format(&OH...I am Laptop.\n New message: {0}&, msg));
#endregion
       现在我们定义被观察者类GofTelecom,它定义了一个Notify()方法,委托GofNews()和事件GofNews。如果大家想参考什么是委托和事件可以参考和。
/// &summary&
/// The Subject class.
/// &/summary&
public class GofTelecom
public delegate void GofNews(string msg);
public static event GofNews NewsE
/// &summary&
/// Notifies every obervers.
/// &/summary&
/// &returns&If notification is successful return true, otherwise false.&/returns&
public static bool Notify()
if (NewsEvent != null)
NewsEvent(Message);
return false;
return true;
public static String Message { get; set; }
      最后通过给GofTelecom对象添加MobilePhone,Tablet和Laptop对象来实现观察者和被观察者之间的关联。
static void Main(string[] args)
IList&IObserver& objObserver = new List&IObserver&();
// Registers observer.
objObserver.Add(new MobilePhone());
objObserver.Add(new Tablet());
objObserver.Add(new Laptop());
// Attachs event and method.
foreach (IObserver ob in objObserver)
GofTelecom.NewsEvent += ob.U
GofTelecom.Message = &Hi Everyone,/n We recommand you new Design Pattern.&;
Console.WriteLine(!GofTelecom.Notify() ? &Notify successful.\n& : &Notify failed.\n&);
Console.ReadKey();
图4示例输出结果
       在系统设计过程中,我们的系统设计基本上都要提供消息提示功能类似于QQ或MSN的消息提示框,而且这个功能恰好是观察者模式(Observer)实现的一种具体实现,在我们实现观察者模式(Observer)消息提示功能之前,先让我们回顾一下推拉模式吧!
推模式和拉模式的区别:
       也许大家会好奇地问“使用推模式和拉模式,有什么区别呢?”
推模式的好处是能够及时响应,想要提供给Observer端什么数据,就将这些数据封装成对象,传递给Observer,缺点是需要创建自定义的事件关联信息,而且它必须继承于EventArgs对象。
       缺点:精确性较差,不能保证能把信息送到客户器。
       拉模式的好处则是不需要另外定义对象,直接将自身的引用传递进去就可以了。
       缺点:不能够及时获取系统的变更。
      .Net 中没有内置的IObserver和IObservable接口(Java中提供该接口类),我们可以通过委托和事件来完成,但是一样面临选择推模式还是拉模式的问题,何时使用哪种策略完全依赖于设计者,你也可以将两种方式都实现了,接下来我们的消息提示功能将通过拉模式实现。
      首先我们通过给窗体控件添加属性TimerStatus,客户端通过Timer来发送消息请求到服务器端,TimerStatus是通过控件公开Timer属性的设置,具体实现如下:
/// &summary&
/// The timer status,
/// it includes base properties to set up timer.
/// &/summary&
[TypeConverterAttribute(typeof(ClockStatusTypeConverter))]
public class TimerStatus
private Timer _timer = new Timer();
private Frequencies _frequencies = Frequencies.S
private int _interval = 23;
private bool _
/// &summary&
/// Paramenterless constructor.
/// &/summary&
public TimerStatus()
: this(Frequencies.Minute, 23, true)
public TimerStatus(Frequencies frequencies, int interval, bool start)
Frequencies =
Interval =
/// &summary&
/// Gets or sets the frequencies.
/// &/summary&
/// &value&
/// The frequencies.
/// &/value&
public Frequencies Frequencies
get { return _ }
set { _frequencies = value; }
/// &summary&
/// Gets or sets the interval.
/// &/summary&
/// &value&
/// The interval.
/// &/value&
public int Interval
get { return _ }
set { _interval = value; }
/// &summary&
/// Gets or sets a value indicating
/// whether this &see cref=&TimerStatus&/& is start.
/// &/summary&
/// &value&
&c&true&/c&
otherwise, &c&false&/c&.
/// &/value&
public bool Start
get { return _ }
set { _start = value; }
public Timer Timer
if (null == _timer)
new Timer();
set { _timer = value; }
     定义一个频率枚举,它提供Second,Minute和Hour单位来设置Timer的频率。
/// &summary&
/// The frequency of timer.
/// &/summary&
public enum Frequencies
       现在我们完成了控件属性TimerStatus的定义,接着把该属性添加到我们自定义Form控件中,我们只需在自定义Form中添加属性如下:
/// &summary&
/// Gets or sets the timer status.
/// &/summary&
/// &value&
/// The timer status.
/// &/value&
[Browsable(true)]
public TimerStatus TimerStatus
if (null == _timerStatus)
return new TimerStatus();
return _timerS
set { _timerStatus = }
      但我们发现自定义控件属性并不能编辑,这是由于控件没有办法把我们自定义类型TimeStatus转换为控件中实现的类型(如:字符串)。所以我们需要添加转换器类。
图5消息提示控件属性定义
/// &summary&
/// Defines &see cref=&TimerStatus&/& type converter.
/// &/summary&
public class TimerStatusTypeConverter : ExpandableObjectConverter
/// &summary&
/// Checks whether can convert from a string to &see cref=&TimerStatus&/& or not.
/// &/summary&
/// &param name=&context&&&/param&
/// &param name=&sourceType&&Source Type.&/param&
/// &returns&Can return true, otherwise false.&/returns&
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
// Can convert from String to ClockStatus.
if (sourceType == typeof(String))
return true;
return base.CanConvertFrom(context, sourceType);
/// &summary&
/// Checks whether can convert from &see cref=&TimerStatus&/& to string or not.
/// &/summary&
/// &param name=&context&&&/param&
/// &param name=&destinationType&&Destination Type&/param&
/// &returns&Can return true, otherwise false.&/returns&
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
if (destinationType == typeof(String))
return true;
return base.CanConvertTo(context, destinationType);
/// &summary&
/// Converts from stirng to &see cref=&TimerStatus&/&.
/// &/summary&
public override object ConvertFrom(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value)
var convertValue = value as string;
if (String.IsNullOrEmpty(convertValue))
return new TimerStatus();
// Defines a enum convert.
var enumConvert = TypeDescriptor.GetConverter(typeof(Frequencies));
// Get the string corresponding to control properties.
var values = convertValue.Split(',');
if (values.Length & 3)
throw new ArgumentException(&Wrong number of arguments&);
int result1 = -1;
bool result2;
if (int.TryParse(values[1].ToString(), out result1)
&& bool.TryParse(values[2].ToString(), out result2))
return new TimerStatus(
(Frequencies)enumConvert.ConvertFromString(values[0]), result1, result2);
return base.ConvertFrom(context, culture, value);
/// &summary&
/// Converts from &see cref=&TimerStatus&/& stirng.
/// &/summary&
public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value, Type destinationType)
if (value is TimerStatus)
if (destinationType == typeof(String))
var clockStatus = value as TimerStatus;
return String.Format(&{0},{1},{2}&,
clockStatus.Frequencies, clockStatus.Interval, clockStatus.Start);
return base.ConvertTo(context, culture, value, destinationType);
      上面我们定义了自定义类型转换器,它提供把TimerStatus类型转换为字符串的方法和通过属性参数创建TimerStatus对象的方法。
图6消息提示控件属性定义
       现在我们定义好了消息提示框,而且我们可以通过属性浏览器直接编辑TimerStatus,如Frequencies设置Timer的频率,Interval时间间隔和Start是否启用Timer。
       每个客户端通过拉模式访问服务器端,当有信息就返回到服务器端显示出来如下:
图7消息提示框设计
1.1.3 总结
       观察者模式(Observer)的优点是实现了抽象与具体的分离,并定义了稳定的更新消息传递机制,类别清晰,并抽象了更新接口。
       但是其缺点是每个观察者对象必须继承这个抽像出来的接口类,这样就造成了一些不方便,比如有一个别人写的观察者对象,并没有继承该抽象类,或者接口不对,我们又希望不修改该类直接使用它。虽然可以再应用Adapter模式来一定程度上解决这个问题,但是会造成更加复杂烦琐的设计,增加出错几率。
观察者模式(Observer)的效果有以下几个优点:
观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体现察者聚集,每一个具体现察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。
观察者模式支持广播通信。被观察者会向所有的登记过的观察者发出通知。
观察者模式(Observer)有下面的一些缺点:
如果一个被观察者对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察考模式时要特别注意这一点。
如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。
虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的
阅读(...) 评论()Chase Elliott speaks with his crew chief Kenny Francis before the start of Sunday’s NASCAR Sprint Cup Series Toyota Owners 400 at Richmond International Raceway. Elliott qualified a solid 16th on Friday and spent the entire 400-lap race Sunday on the lead lap and finished a respectable 16 th .
Alex Trautwig
Getty Images
Chase Elliott leads a pack of cars during the NASCAR Sprint Cup Series Toyota Owners 400 at Richmond International Raceway on Sunday, April 26, 2015 in Richmond, Va.
Jeff Curry
Getty Images
Chase Elliott looks on with his parents Bill and Cindy during the national anthem before Sunday’s Toyota Owners 400 at Richmond International Raceway.
Alex Trautwig
Getty Images
Sprint Cup driver Chase Elliott greets fans during driver introductions prior to the start of the NASCAR Sprint Cup auto race at Richmond International Raceway in Richmond, Va., Sunday, April 26, 2015.
Steve Helber
By Jim Utter
Related content}

我要回帖

更多关于 observer模式 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信