zoukankan      html  css  js  c++  java
  • Android开发,别把Java当Javascript

       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的风格,那样你会很难维护。

  • 相关阅读:
    PHPUnit断言详情
    dev tools杂谈
    sublime text3 + python3.5 ide
    文件传输接收sz、rz命令用法
    Linux编辑器vi使用方法详细介绍
    vi编辑字符串替换及sed用法
    Selenium实战(一)——浏览器实例
    Python的数据库连接
    Cypress测试框架——一个简单的测试用例
    Cypress测试框架——入门1
  • 原文地址:https://www.cnblogs.com/liyunfan/p/3499404.html
Copyright © 2011-2022 走看看