您的位置:首页 > 移动开发 > Android开发

Android开发,别把Java当Javascript

2013-12-31 14:22 453 查看
   Android开发中,匿名类的应用使得开发更加灵活,而匿名类的滥用却让程序变得杂乱无章、难以维护。程序员都是喜欢偷懒的,我们常常看到一个Activity类中布满了匿名类,有Thread、有Handler、有Adapter、有各种Listener以及给匿名类传递数据的final变量,给人的感觉就像随地大小便,很不文明。

Java毕竟不是Javascript,没有闭包和没有匿名函数,把面向对象设计的语言用函数式编程的思想来写是很牵强的。下面贴一段JS代码:

MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {
if(err) throw err;

db.dropDatabase(function(err, done) {

db.createCollection('test_custom_key', function(err, collection) {

collection.insert({'a':1}, function(err, docs) {

collection.find({'_id':new ObjectID("aaaaaaaaaaaa")}).toArray(function(err, items) {
console.dir(items);
// Let's close the db
db.close();
});
});
});
});
});


得益于JS的闭包、匿名函数、函数即变量等特性,JS开发者可以将函数嵌套发挥到令人叹为观止的地步,而且即使套了很多层,也不会显得很臃肿。你能想想如果Java套这么多层会是什么效果吗?或许编辑器都显示不下最长的缩进了,但能多Android开发者就好这口,来看个例子:

public class MyActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((ListView) findViewById(R.id.listview)).setAdapter(new BaseAdapter() {

@Override
public View getView(int arg0, View arg1, ViewGroup arg2) {
if (arg1 == null) {
arg1 = LayoutInflater.from(MyActivity.this).inflate(
R.id.feed, arg2, false);
}

arg1.findViewById(R.id.subject).setOnClickListener(
new OnClickListener() {

@Override
public void onClick(View v) {
final Handler handler = new Handler(
new Callback() {

@Override
public boolean handleMessage(
Message msg) {
// 此处省略50行
return false;
}
});

new Thread(new Runnable() {

@Override
public void run() {
// 此处省略100行
handler.sendEmptyMessage(0);
}
}).start();
}
});

return arg1;
}

// 。。。。。。
});
}
}


这是个真实的例子,其中很多习惯很多安卓开发者也有。这个onCreate函数竟然有近千行代码,已经完全丧失可读性了。如果你走了有人来接替你的活儿,看到这样的代码他一定会把你骂死。

下面我就Android开发中常见的匿名类给出自己的替代方案,仅供参考,错误之处还请指证。

用继承接口代替匿名类

这种方式适合各种Listener,这里以OnClickListener为例作说明。绑定事件一般是在onCreate时完成的,所以在onCreate中可能会有很多个OnClickListener的匿名类,比如:

findViewById(R.id.button).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// ....
}
});


这时onCreate方法就会变得冗长,而且包含很多不应该出现在onCreate中的处理逻辑,如果我们让Activity去实现OnClickListener,将所有点击处理的listener都设为这个activity,在onClick中再根据view.getId()来分支处理,程序的结构就会紧凑很多:

public class DummyActivity extends Activity implements OnClickListener {
//.....

@Override
protected void onCreate(Bundle savedInstanceState) {
for(int id : in new int[] { R.id.button }) {
findViewById(id).setOnClickListener(this);
}
}

@Override
public void onClick(View arg0) {
switch(arg0.getId()) {
case R.id.button:
// ......
break;
}
}
}


包括onLongClickListener等针对单一View的Listener都可以通过让Activity继承接口的方式来操作。如果是针对列表项的ItemListener,建议让Adapter去继承接口。

用子类代替匿名类

如果一个Activity中有AdapterView的子类,如ListView、GridView,就会设置相应的Adapter,除了最简单的情形可以用SimpleAdapter、ArrayAdapter直接映射,很多情况都都需要继承BaseAdapter之类后重写一些方法,逻辑比较简单时用内部类不失为可取办法。例如很多人喜欢在onCreate中这么写:

((ListView)findViewById(R.id.listView)).setAdapter(new BaseAdapter() {
@Override
public View getView(int arg0, View arg1, ViewGroup arg2) {
//......
}
//......
});


为了不在onCreate参杂不相关的逻辑,保持代码结构合理,你可以尝试这样处理:

public class DummyActivity extends Activity {
//.....

@Override
protected void onCreate(Bundle savedInstanceState) {
((ListView)findViewById(R.id.listView)).setAdapter(new MyAdapter(....));
}

private static class MyAdapter extends Base Adapter{
MyAdapter(...) {
.......
}

@Override
public View getView(int arg0, View arg1, ViewGroup arg2) {
.........
}
}
}


至于static与否则取决于你是否要用到动态成员变量了,这种方式使得参数传递也更加方便:只需通过构造函数传入,不必通过final关键字。

用外部类代替匿名类

对于Adapter这类逻辑简单的类可以用内部类处理,如果涉及到更加复杂的逻辑,比如数据处理、I/O、数据库操作等,建议用外部类使各个类的业务属性尽可能单一。比如Thread类,跟Activity类相关度本来就很低,为了偷懒非得硬生生塞进Activity中显然是不合适的,无论是匿名类还是子类的形式,这里就不举具体例子了。至于外部类的命名,如果想不到合适的名字,可考虑前缀命名,比如现在有一个DummyActivity,之前在里面塞了一个MyThread,那提出来再叫MyThread显然不合适,就以前缀命名的方式改为DummyActivityThread就一目了然了。

小结

Javascript是门很优秀的语言,拥有函数式编程的诸多特性,合理的灵活嵌套可以使代码紧凑而优雅,而Java是一门严格面向对象的语言,匿名类嵌套的滥用会让你的程序臃肿混乱,建议不要把Java写成了Javascript的风格,那样你会很难维护。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: