By 高焕堂 2010/02/03
小强龙的天空:框架设计策略
1. 小强龙的天空
俗语说:强龙不压地头蛇。意味着,强龙与地头蛇的合作可创造双赢的局面。首先来区分地头蛇与强龙的互补角色:
- 地头蛇-- Android应用程序开发者。
- 强龙-- Android框架(Framework)和链接库(Library)组件开发者。
经常,还会出现介于两者之间的新角色:小强龙。例如,强龙(如Google)已经在Android里面开发了Activity、Service、SurfaceView等基类,提供给地头蛇来使用或撰写子类别来继承之。Android框架已经促成了Google强龙与全世界各区域的地头蛇(即Android应用程序开发者)美好的合作局面了。然而,因为Android是跨应用领域(Application Domain)的通用性框架,未能顾及特定应用领域里的通用性小框架,例如VOIP、Flash动画等领域。因而,Android框架也创造了小强龙的天空:开发特定领域里的小框架和链接库组件(含Java类别和C++类别等)。小强龙补充了强龙的不足,让Android框架内含更加丰富、充实。让地头蛇享受更多的方便,迅速开发出更多样化的Android应用软件系统。
2. 小强龙Java组件之例
小强龙的角色就是要以Java或C++类别来表达特定领域的知识,然后提供给地头蛇使用。而且常常会设计Java或C++的基类来作为他与地头蛇之间的衔接接口(Interface)。[歡迎光臨 高煥堂 網頁: http://www.cnblogs.com/myEIT/ ]
例如,先从一个简单的Java类别说起,如下范例Ex01:
范例代码如下:
// BiAdder.java
package com.misoo.adder;
public class BiAdder {
private int a, b, carry, sum;
public void set_digits(int ia, int ib)
{ a = ia; b = ib; }
public void execute()
{ carry = a & b; sum = a ^ b; }
public int get_carry() { return carry; }
public int get_sum() { return sum; }
}
//ac01.java
package com.misoo.pk01;
import com.misoo.adder.BiAdder;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
public class ac01 extends Activity implements OnClickListener {
private Button btn, btn2;
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
btn = new Button(this); btn.setBackgroundResource(R.drawable.heart);
btn.setId(101); btn.setText("run");
btn.setOnClickListener(this);
LinearLayout.LayoutParams param =
new LinearLayout.LayoutParams(120, 55);
param.topMargin = 10;
layout.addView(btn, param);
btn2 = new Button(this); btn2.setBackgroundResource(R.drawable.heart);
btn2.setId(102); btn2.setText("exit");
btn2.setOnClickListener(this);
layout.addView(btn2, param);
setContentView(layout);
}
public void onClick(View v) {
switch(v.getId()){
case 101:
BiAdder ba = new BiAdder();
ba.set_digits(1, 1);
ba.execute();
setTitle("sum = " + String.valueOf(ba.get_carry()) +
String.valueOf(ba.get_sum()));
break;
case 102: finish(); break;
}}}
在这个范例里,地头蛇自己撰写BiAdder.java类别,这是一个特定领域的简单类别,写完了之后,地头蛇自己撰写应用类别ac01(它继承了大强龙的Activity基类),来使用BiAdder类别。如果采取强龙/地头蛇的合作模式来分工撰写上述的范例程序时,小强龙该做些什么呢?答案是:提供一个Java基类,让地头蛇写子类别来继承之。如下范例Ex02:
范例代码如下:
//BiAdder.java
package com.misoo.adder;
public class BiAdder {
private int a, b, carry, sum;
public void set_digits(int ia, int ib)
{ a = ia; b = ib; }
public void execute()
{ carry = a & b; sum = a ^ b; }
public int get_carry(){ return carry; }
public int get_sum(){ return sum; }
}
//Adder.java
package com.misoo.adder;
abstract public class Adder {
private BiAdder ba;
public Adder()
{ ba = new BiAdder(); }
public void exec(){
ba.set_digits(onGetX(), onGetY());
ba.execute();
}
public int get_carry()
{ return ba.get_carry(); }
public int get_sum()
{ return ba.get_sum(); }
abstract public int onGetX();
abstract public int onGetY();
}
//myAdder.java
package com.misoo.pk01;
import com.misoo.adder.*;
public class myAdder extends Adder {
public myAdder() { super(); }
@Override public int onGetX() { return 0; }
@Override public int onGetY() { return 1; }
}
// ac01.java
package com.misoo.pk01;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
public class ac01 extends Activity implements OnClickListener {
private Button btn, btn2;
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
btn = new Button(this); btn.setBackgroundResource(R.drawable.heart);
btn.setId(101); btn.setText("run");
btn.setOnClickListener(this);
LinearLayout.LayoutParams param =
new LinearLayout.LayoutParams(120, 55);
param.topMargin = 10;
layout.addView(btn, param);
btn2 = new Button(this); btn.setBackgroundResource(R.drawable.heart);
btn2.setId(102); btn2.setText("exit");
btn2.setOnClickListener(this);
layout.addView(btn2, param);
setContentView(layout);
}
public void onClick(View v) {
switch(v.getId()){
case 101:
myAdder adder = new myAdder();
adder.exec();
setTitle("sum = " + String.valueOf(adder.get_carry()) +
String.valueOf(adder.get_sum()));
break;
case 102: finish(); break; }
}
}
小强龙开发BiAdder类别,然后也开发Adder基类。而地头蛇则撰写myAdder子类别来继承Adder基类,因此结合了小强龙和地头蛇双方的智慧。最后,地头蛇撰写ac01子类别来继承大强龙的Activity基类,也使用了myAdder子类别,终于将大强龙、小强龙和地头蛇三方的智慧结合起来了。
3. 小强龙框架设计策略:以线程为例
在刚才的范例Ex02里,小强龙负责撰写的BiAdder和Adder两个类别都是由主线程来执行的。由于地头蛇看得到BiAdder类别里的代码,其中并无费时的函数,所以能确保不会仿碍到UI线程的畅通。想一想,如果小强龙将BiAdder类别封闭起来,地头蛇因为无法看到BiAdder类别的内容,而无法确保BiAdder里的函数不会仿碍到UI线程的畅通。此时,比较贴心的小强龙,通常会在Adder基类里处理线程问题,让地头蛇开发所开发的ac01类别会变得简单许多(因为不必处理线程问题)。如下之范例Ex03:
范例代码如下:
// IListener
package com.misoo.adder;
public interface IListener {
public void callback();
}
//BiAdder.java
package com.misoo.adder;
public class BiAdder {
private int a, b, carry, sum;
public void set_digits(int ia, int ib)
{ a = ia; b = ib; }
public void execute(){
try { Thread.sleep(6000);
} catch (InterruptedException e) { e.printStackTrace(); }
carry = a & b;
sum = a ^ b;
}
public int get_carry(){ return carry; }
public int get_sum(){ return sum; }
}
//Adder.java
package com.misoo.adder;
import android.os.Handler;
import android.os.Looper;
abstract public class Adder {
private BiAdder ba;
private static IListener plis;
public Adder() { ba = new BiAdder(); }
public void exec(){
ba.set_digits(onGetX(), onGetY());
new Thread(){ public void run() {
ba.execute();
Handler h = new Handler(Looper.getMainLooper());
h.post(new myRun());
}}.start();
}
public int get_carry(){ return ba.get_carry(); }
public int get_sum(){ return ba.get_sum(); }
abstract public int onGetX();
abstract public int onGetY();
public static void setListener(IListener listener){ plis = listener; }
class myRun implements Runnable{
public void run() { plis.callback(); }
}}
//myAdder.java
package com.misoo.pk01;
import com.misoo.adder.*;
public class myAdder extends Adder {
public myAdder(){ super(); }
@Override public int onGetX() { return 1; }
@Override public int onGetY() { return 1; }
}
// ac01.java
package com.misoo.pk01;
import com.misoo.adder.IListener;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
public class ac01 extends Activity implements OnClickListener {
private Button btn, btn2;
private myAdder adder;
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
btn = new Button(this); btn.setBackgroundResource(R.drawable.heart);
btn.setId(101); btn.setText("run");
btn.setOnClickListener(this);
LinearLayout.LayoutParams param =
new LinearLayout.LayoutParams(120, 55);
param.topMargin = 10;
layout.addView(btn, param);
btn2 = new Button(this); btn.setBackgroundResource(R.drawable.heart);
btn2.setId(102); btn2.setText("exit");
btn2.setOnClickListener(this);
layout.addView(btn2, param);
setContentView(layout);
//-----------------------------------------
myAdder.setListener(new myListener());
}
public void onClick(View v) {
switch(v.getId()){
case 101:
adder = new myAdder();
adder.exec();
setTitle("executing..."); break;
case 102: finish(); break;
}}
class myListener implements IListener {
public void callback() {
setTitle(Thread.currentThread().getName() + ", sum = " + String.valueOf(adder.get_carry()) +
String.valueOf(adder.get_sum()));
}}}
小强龙考虑到地头蛇可能会用主线程来执行myAdder的各个函数。由于BiAdder::execute()函数需要较长的执行时间,可能会影响到主线程的流畅性。于是,在Adder::exec()里诞生子线程来执行BiAdder::execute()函数。等到执BiAdder::execute()行完毕,就透过MQ要求主线程执行myListener::callback()函数。在执行myListener::callback()时,子线程已经计算出carry和sum值了。这时主线程可取得正确的carry和sum的值。所以这样的写法是对的。◆
[Go Back]