美文网首页android经典收录技术与人生View
Android:你是如何把Activity写的如此“万能”的

Android:你是如何把Activity写的如此“万能”的

作者: 牛晓伟 | 来源:发表于2016-04-15 06:57 被阅读7959次

前言


自己android开发也有些年头了,每每回想起作为初学者的时候自己写的代码,自己会有种喷自己的冲动,代码写的太渣了。因此想着自己要总结下以前代码中的不合理的地方,希望能给初学者一些帮助。我希望这是一个系列的文章。

本节内容


一个“万能”的Activity是什么样子,“万能”的Activity有哪些不好的地方

开始编写“万能”的Activity


作为了一个初学者,有可能会有好多的朋友把Activity写的很“万能”,当然没有更好。那我就以一个登陆模块为例子,来说说一个“万能”的Activity是怎么产生的,以下代码多为伪代码。

编写activity_login.xml文件,这里就简单写下伪代码:

  一个输入用户账号的 EditText
  一个输入密码的   EditText
  一个登陆按钮 Button

编写LoginActivity,LoginActivity包含初始化activity_login.xml中views的功能,还包含给登陆按钮加监听器的功能,下面看下关键的代码片段

   public LoginActivity extends Activity{
          private EditText  mUserNameView, mPasswordView;
          private Button mLoginView;
          //该方法会被onCreate方法调用
          public void initViews(){
                 .......
                  各种findViewById.....代码
                  
                  //给登陆按钮加监听器
                  mLoginView.OnClickListener(new View.OnClickListener() { 
                        @Override 
                         public void onClick(View v) {    
                        }
                  });
          }
   }

现在的LoginActivity中的代码是不是还很清爽,干净。它只做与UI相关的工作。

具有验证功能的LoginActivity
那接着要在登陆按钮的监听器方法实现验证账号,密码是否有效的功能,继续接着完善代码

    mLoginView.OnClickListener(new View.OnClickListener() { 
          @Override 
          public void onClick(View v) {
               
                String userName = mUserNameView.getText();
                String password = mPasswordView.getText();
                 //验证用户输入的用户名,密码是否合法
                if(!validate(userName) || !validate(password)){
                        告诉用户输入的用户名或密码不合法,并做一些其他的工作
                 }
          }
     });
    
     //验证给定的字符串是否合法,true 合法,false 不合法
     private  boolean validate(String str){

     }

现在的LoginActivity已经有业务代码出现了,我们该实现登陆功能了。

具有登陆功能的LoginActivity
在监听器中增加登陆功能

    mLoginView.OnClickListener(new View.OnClickListener() { 
          @Override 
          public void onClick(View v) {
                验证用户输入的用户名,密码是否合法代码...
                if(都合法){
                      //开始登陆
                      login(userName,password);
                }
          }
     });
      //登陆方法,用伪代码来写下网络请求
     private void login(String userName,String password){
          
            HttpClient.getInstance().login(userName,password,
                   new ResponseListener(){
                          
                           public void failed(Failed failed){
                                  做失败相关的处理工作,比如给用户提示
                                  把密码输入框清空,还比如登陆次数限制等
                           }

                           public void success(Response response){
                                  对数据进行解析,跳转到app主页或其他界面
                           }
                   });
     }

具有数据解析,存储功能的LoginActivity
当我把登陆功能做好后,这时候产品又提了新需求,需要在用户登陆成功后,把用户相关的数据返回,并保存。那没辙只能按要求来做,但是幸运的是需求很简单,只需要修改下登陆成功方法就ok。

      public void success(Response response){ 
          做成功相关的处理工作
          //暂且把用户信息的类叫做UserInfo,从json中解析数据,假设response.getContent()存在
          String jsonContent = response.getContent();
          JsonObject jsonObject = new JsonObject(jsonContent);
          UserInfo userInfo = new UserInfo();
          userInfo.name = jsonObject.optString("name");
          userInfo.userId = jsonObject.optString("userId");
          其他字段的解析......
          //保存userInfo信息到数据表中,假设userDatabase已经存在
          userDatabase.save(userInfo);

          跳到app的主页
      }

到此,登陆功能开发完毕,LoginActivity最后的代码是这样

     public LoginActivity extends Activity{
          private EditText  mUserNameView, mPasswordView;
          private Button mLoginView;

          public void initViews(){
                 .......
                  各种findViewById.....代码
                  
                  //给登陆按钮加监听器
                  mLoginView.OnClickListener(new View.OnClickListener() { 
                        @Override 
                         public void onClick(View v) {  

                              String userName = mUserNameView.getText();
                              String password = mPasswordView.getText();
                              //验证用户输入的密码是否合法
                              if(!validate(userName) || !validate(password)){
                                  告诉用户输入的用户名或密码不合法
                              }  else{
                                  //开始登陆
                                  login(userName,password);
                              }
                        }
                  });
          }

           //登陆方法,用伪代码来写下网络请求
           private void login(String userName,String password){
          
                HttpClient.getInstance().login(userName,password,
                   new ResponseListener(){
                          
                           public void failed(Failed failed){
                                  做失败相关的处理工作,比如给用户提示
                                  把密码输入框清空,还比如登陆次数限制等
                           }

                           public void success(Response response){
                                   做成功相关的处理工作
                                  //暂且把用户信息的类叫做UserInfo,从json中解析数据,假设response.getContent()存在
                                  String jsonContent = response.getContent();
                                  JsonObject jsonObject = new JsonObject(jsonContent);
                                  UserInfo userInfo = new UserInfo();
                                  userInfo.name = jsonObject.optString("name");
                                  userInfo.userId = jsonObject.optString("userId");
                                  其他字段的解析......
                                  //保存userInfo信息到数据表中,假设userDatabase已经存在
                                  userDatabase.save(userInfo);

                                  跳到app的主页
                           }
                 });
           }

            //验证给定的字符串是否合法,true 合法,false 不合法
           private  boolean validate(String str){

           }
   }

到此登陆模块功能已经开发完成,LoginActivity由开始的清爽,干净的只关心U的代码,变成了现在的“万能”Activity,LoginActivity都做了哪些工作:

  • 处理UI
  • 处理用户名,密码合法性验证业务
  • 处理数据解析,数据存储

当然你会说现在的LoginActivity的代码也就将近100行,修改起来还是很容易的,但是随着业务的增长,谁能保证LoginActivity代码不会越来越多,包含的业务代码不会更多。LoginActivity只是"万能"Activity的一个缩影而已。

万能是好事情,但是得看万能是通过什么方式实现的,假如是通过把好多小功能分散到各自的类中,然后万能类通过把这些小类组合在一起的万能是真材实料的万能。若是通过把好多小功能全部放在一个类中使得这个类变的“万能”了,这种“万能”是不好的。

“万能”Activity缺点
我总结下“万能”Activity缺点

  • 引起"万能"Activity的变化因素很多,所以动不动就得修改它,没办法使得由于修改引入的bug的机率降到最低。
  • 业务功能没法复用
  • 这样的Activity可维护性,可阅读性都不好,耦合很高。

所以为了以后长远考虑,遇到“万能”Activity一定要大胆的重构,虽然当前重构需要花很多时间,但是以后是一劳永逸的,因此让“万能”Activity不在万能,让Activity只做与UI相关的工作就足够了。

总结

关于“万能”Activity的事情就聊到这,请看Android:“万能”Activity重构篇
代码清爽,干净了,阅读起来精神倍儿爽,一口气阅读100行不成问题!

本人微信:704451290

本人公众账号

相关文章

网友评论

  • 黑白咖:签到
  • benzly:我X,感觉正要高潮,却突然发现G点在下一篇....
  • 头撞豆腐:用MVP模式写,P桥梁,V用来判断用户是否按下按键和传递当前的账户密码,M层用来判断密码的时效性,
    然后在调用V层的回调接口,传递结果,这样可能就更不止100行了~~~
  • MC_DEV_JIN:下一篇麽😍
    牛晓伟: @MC_DEV_JIN 是的
  • Zack_zhou:上个月看到过这篇文章,图像想起来现在应该会更新下一篇了,可以还是没有来。
    有打算写下一篇吗?
    牛晓伟: @Zack_zhou 快出来了,最近忙
  • 2d8533a83ac8:下一篇什么时候出来?
  • MyronMi:不开心,我还等着下一篇的呢,作者偷懒~
  • MeloDev:谢谢牛老师的分享,期待着如何重构
    MeloDev:@牛晓伟 。。。哈哈可能还没真正离开学校吧,习惯了~转载了您的dagger2文章,写的太棒了
    牛晓伟: @MeloDev 哥们,叫我老师吓傻我也,可不敢用老师这个词
  • Echo剑心:坐等下一篇啊
  • johnzz: :smile: 多谢楼主分享。
  • b8f1f5b2b49f:坐等下一篇,啥时候更新呢?
  • totato:等不及想看下篇了
  • RicoX2016:我来预测一下楼主下一篇会怎样优化,。首先是网络请求参数的封装,用户名密码邮箱等以一个接口来扩展,各种不同需求需要的不同参数,请求返回,有成功有失败,或者有返回数据,都封装在接口里,回调,扩展,第三个就是对于输入参数的检查等放到工具类中,这样activity 代码少了很多,模块也分出去了……
  • 72f72e2ceb45:谢谢分享
  • 2cab9682f267:这代码好熟悉
  • 徐慕容:引出MVVM。
  • 键盘男:MVP,什么都不说
  • b09f682c4d8b:等待下一篇
  • Max____:封装参考:把登陆逻辑(包括验证空输入、字符限制、网络请求登陆、本地登录状态保存、密码加密等)封装在一个类中,比如叫LoginUtil,那么在任何需要登陆操作的位置使用时就是下面这样:
    new LoginUtil().login(username, password) {
    @Override
    public void onSuccess() {
    // 登陆成功 do something
    }
    @Override
    public void on Failure() {
    // 登陆失败 do something
    }
    }
    Max____:@牛晓伟 那就根据具体需要进行封装吧,我大概写到这种程度就够用了。
    牛晓伟:@maodq 这样封装没问题,还有没有更好的 把 其他的业务逻辑也抽出来,让这些业务逻辑形成一种层级关系,
  • M星空:看完标题,还以为是说封装一个baseactivity呢,结果上当了。下篇才是重点!
    郑土强ztq:@M星空 我也是这样想的呢
    FredKang:@M星空 应该会用mvp吧
  • 2fc6d513dea5:期待下一篇 :+1:
  • 4875efc6c92b:这种设计业务逻辑层与view混在一起 后期维护你会后悔的
    牛晓伟: @Android_Dev 是的
  • 小小小小小粽子:期待下一篇如何解决万能,如何重构
  • 小鄧子:万能Activity或者万能类,是我最讨厌的东西之一。
    牛晓伟: @小鄧子 我也是
  • AndroidKy:接下来一片就是MVP。
  • 4ebeb9286939:推荐AbstractMVP,github开源项目,很不错的架构思想,让Activity只做与UI相关的工作
    牛晓伟: @我听松风 啥链接
    b378ed18a288:能给个链接吗?谢谢!
    牛晓伟:@因爲一个人所以一个人 好的,学习下
  • 姚瑶大坏蛋:期待下一篇
  • chenzzz:一不小心,我现在还在写这样的万能activity
  • chenzzz:解决之道是不是引入mvc或是mvvc模式?
    FredKang:@陈司机 大兄弟!mvvm
  • d986d284aade:这个代码段虽然“万能” 但程序的语句还是清晰的 我最怕遇到万能的同时 语句不清晰 业务逻辑隐藏在意想不到的地方(比如数据库方法)
  • 倾城_之泪:好期待下一篇!文中和我写万能Activity的姿势一模一样
  • b885acde512c:期待下篇。
  • 子茗:用心良苦,感谢楼主!
    牛晓伟: @小牛在狂奔 😊

本文标题:Android:你是如何把Activity写的如此“万能”的

本文链接:https://www.haomeiwen.com/subject/srsglttx.html