Android歌词秀设计思路(6)运用Proxy设计模式简化歌词播放服务的使用
开始开发歌词秀的时候还是夏天,没有想到写这篇文章的时候大连已经迎来的今年的第一次大规模降温。多少有点冬天的感觉了。
上一篇文章我们已经介绍了,带有歌词播放功能的服务,按说接下来就该是利用歌词播放服务的应用程序了。不过我们在这里要先介绍另外一个类:LyricPlayerServiceProxy,先看一下这个类在整个软件中的位置。
为什么要有这么一个类呢?
原因是:Android里的服务用起来还不是很方便.
先看下面一段来自Android文档的的代码,这段代码是说明如何使用Service的。
链接:http://developer.android.com/reference/android/app/Service.html
private LocalService mBoundService;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. Because we have bound to a explicit
// service that we know is running in our own process, we can
// cast its IBinder to a concrete class and directly access it.
mBoundService = ((LocalService.LocalBinder)service).getService();
// Tell the user about this for our demo.
Toast.makeText(Binding.this, R.string.local_service_connected,
Toast.LENGTH_SHORT).show();
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
// Because it is running in our same process, we should never
// see this happen.
mBoundService = null;
Toast.makeText(Binding.this, R.string.local_service_disconnected,
Toast.LENGTH_SHORT).show();
}
};
void doBindService() {
// Establish a connection with the service. We use an explicit
// class name because we want a specific service implementation that
// we know will be running in our own process (and thus won't be
// supporting component replacement by other applications).
bindService(new Intent(Binding.this,
LocalService.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
void doUnbindService() {
if (mIsBound) {
// Detach our existing connection.
unbindService(mConnection);
mIsBound = false;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
doUnbindService();
}
代码本身不算复杂,但是有一点比较讨厌,用户在调用doBindService方法以后,不能立即得到可供使用的服务的实例(mBoundService)。要想使用可供使用的服务的实例,必须要等到ServiceConnection的onServiceConnected方法被调用之后才可以。多少还是有一些不方便的。怎么解决这个问题呢。
这里我们使用了Proxy(代理)设计模式。在GOF设计模式中代理模式的几个例子有远程代理,虚代理,保护代理,智能指引等,这里的用法和虚代理比较相似,但目的不同。虚代理的目的是有关资源的,这里是为了简化使用。
找一个生活中真正代理的例子说明一下这种区别吧。
说有一个大牌明星要举办一场演唱会,当然事前要做好多准备工作,比如开会啦什么的,如果每次都是大牌亲自去,一个是档期排不开,另外也太贵了,于是好多事就由经纪人代劳,直到真正演出是大牌才出场。这叫虚代理。
和大牌同一个经济公司有一个刚入行的小演员,公司也给他指派了经纪人。由于他还不能独立演出,公司就安排他给大牌垫场。可是这人有个毛病,早上爱睡懒觉,经常迟到。于是公司就指派他的经纪人先去接受任务,等小演员来了在转告给他。这样就不会耽误大牌的演出了。
这就是我们今天要说明的场景。为了减轻使用者的负担,我们运用了Proxy模式。
先看看数据成员。
private LyricPlayerService mPlaybackService = null ;
这就是我们的小演员了。经济人虽然不迟到,但是戏还是要演员演。这是我们真正实现功能的服务。
接下来就是需要交代给演员做的事了。现有经纪人保管着。
private ServiceConnectionListener mConnectionListener = null;
private LyricPlayerService.LyricPlayerListener mLyricListener = null;
private MediaPlayerService.NotificationProvider mNotificationProvider = null;
当然了,一旦见到小演员,把接到的任务交代给他那也是必须的。
private ServiceConnection mPlaybackConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mPlaybackService = ((LyricPlayerService.LocalBinder)service).getService();
mPlaybackService.setLyricPlayerListener(mLyricListener);
mPlaybackService.setNotificationProvider(mNotificationProvider);
if(mConnectionListener != null){
mConnectionListener.onServiceConnected();
}
}
public void onServiceDisconnected(ComponentName className) {
mPlaybackService.setLyricPlayerListener(null);
mPlaybackService = null;
if(mConnectionListener != null){
mConnectionListener.onServiceDisconnected();
}
}
};
演员新入行,有时需要把一个指令分解,一步一步的指挥。经纪人也不容易啊。
void startAndBindService(){
mContextWrapper.startService(new Intent(mContextWrapper ,LyricPlayerService.class));
mContextWrapper.bindService(new Intent(mContextWrapper, LyricPlayerService.class), mPlaybackConnection, Context.BIND_AUTO_CREA
补充:移动开发 , Android ,