BaseActivity 的封装思想

阅读 10614
收藏 730
2017-03-06
原文链接:url.cn

BaseActivity在我们的项目中非常常用,所以,有一个好的封装会让我们的开发事半功倍 ,但是他怎么样封装才能方便我们的开发呢?


有人说现在流行的是mvp架构的程序,但我想问你,mvp架构的目的是什么呢? 他就是为了让代码的阅读性和可拓展性更强,同样,我写这篇博客的目的也是,而且我认为,在一些界面,根本就没必要使用mvp架构,架构是人写出来的,是死的东西,而人是活的,不要舍本逐末。当然,我也知道mvp架构的好处,所以,在这里提一句,我的这个封装是为了让一些简单的界面,常用的界面更加简洁的书写出来。没有必要说我这个app的架构是mvp就全用他。


Mvp与mvvm对比:

MVP

MVVM

Mvp与mvvm都是现在比较流行的架构,mvvm是基于google的data-binding绑定机制,现在用的人较MVP的少一些,但是两种架构的原理是一样的,但本人对mvvm接触的也不深,这里不做过多评价。 
mvp架构呢,是一个将视图层和操作层拆分的非常明确是架构,虽然代码写起来会比普通写法多一些,但是他的维护性更强,对于大型项目有非常好的帮助。


但是,我们如果选择了mvp架构,就要把所有界面都写成MVP的形式吗?看一下下面的关于登录界面的截图:

这是我之前写的一个mvp架构的登录界面,类接口爆炸有没有,他确实有他的优点,但是缺点也非常明显,就是类的数量爆炸,那么我们是不是应该在一些简单的界面不使用这种架构呢,这就是我开发这个框架的目的,服务于各种架构,但又脱离这些架构,简单来讲,就是我代码写的少,并且清晰明了。


BaseActivity的封装:

我们一般会在baseActivity中封装一些使用频率比较高的方法,方便界面调用,下面我们看一下github中一个star数在2000左右的一个开源框架在base中封装了什么?


这两张图片是FastDev4Android框架的base封装,他在里面都封装了什么呢,生命周期的各个方法,Activity的堆栈管理,toast显示,和intent跳转,这些东西都是我们在开发中常用的方法,封装到里面方便我们调用,但是我认为这些东西不全面,下面看看我在base中封装了什么?


  1. 跳转方法

  2. 接收传值方法

  3. Android 4.4版本以上沉浸式的封装

  4. Toolbar的封装

  5. 界面之间消息传递的封装(EventBus)

  6. 加载中动画的封装


有了这些封装,我们在基本的activity中就减少了很多代码,比如加载动画,我们封装完成之后,可能只需要一个方法的调用,loading界面就出现了。


那么就让我们来一点点把这些常用方法封装进去。

首先,baseActivity中oncreate的第一个方法4.4版本以上的沉浸式,这里面new出来的对象是我们自己写的,sdk不提供,具体代码大家可以参考我的项目源码,在baseac中封装了这个方法,我们只需要在style中声明一组属性,在xml布局中使用他,就可以完成沉浸式了。

第二个方法就是获取Intent的传值,我们在这里进行获取工作,下面会有方法去实现它,接下来的是eventbus的注册,初始化ac布局,在oncreat中都是初始化处理,下面都有指定方法去完成它,最后一个是toolbar初始化,我在这里findid使用的id是在ids中注册的,如果我们想使用base提供的toolbar,在xml中声明出来toolbar控件后让他使用这个存在的id就可以了,如果不想使用,有其他需求,则只需在xml中不使用这个id就可以,代码自己判断就不会走到下面的toolbar初始化。


接下来这张图片上方是oncreat的结尾,下面是这几个初始化的接口方法,继承baseac就会强制重写,让我们分别在指定的位置写指定的代码,条理更加清晰。


这张图片的第一个方法是在前面说的获取intent的bundle消息,我们强制使用bundle,可以传递各种数据,获取时只需在这个方法里面对指定对象赋值就可以了,如果bundle为空,则不走该方法。InitTitle,oncreat中初始化toolbar的方法,同样如果不使用指定id,该方法也不会进入,setTItle,很明显,为title赋值,这是在允许toolbar初始化时可以调用的方法


这张图片第一个方法是在oncreat中提到的4.4沉浸式,在上方的api19可以看出,只有在19及以上时才可以执行,下面是对eventbus的封装,我讲eventbus的发送消息基类已经封装好了,可以放任意对象,我们在继承base后,后自动重写eventbus接受消息方法,在提供的数据里进行判断,获取数据,比如我们让所有存在界面接收刷新消息,Eventcenter中有code这个属性,我们设定刷新的指定code,界面在接收消息判断得到这个code知道是刷新指令,就执行刷新命令了。


这个就是我们是eventbus消息基类,我们发送的data是泛型结构,所以在指定位置进行强转就可获得指定对象了。



效果图:

这三张图片写的注释就非常清晰,加载loadingdialog的方法,toast的方法,和界面销毁解绑eventbus。其中这里的loading效果有两个,一个是放win10加载小球转动的效果,一个是我自己写的动画,支持定制图片。效果如上图


接下来的就是intent跳转传值方法,之前我说过,我们如有传值,强制使用bundle,就是在这里强制使用的。


以上就是我的baseac中的所有封装,有人会说这些代码也没有什么特别减少我们开发的东西呀,别急,baseac是服务于所有的ac我们只是把大家都能用到的东西放在里面,另外经常出现的代码我们会再次封装也就是我们接下来要讲的YzsBaseListActivity,YzsBaseHomeActivity。


YzsBaseListActivity

列表类的经常出现,比如我们的消息列表,新闻列表,也就是这样的效果

这样的效果我们如果用普通方式写起来要写多少呢,来看看github上的一个开源项目androidFire新闻项目是怎么写的?

这就是他在Activity中写的代码,有20行左右是获取api数据,我们不用去看,剩下的代码也不少呀,而且他的Adapter还是在另一个类中写的,是不是很多,如果我们使用YzsBaseListActivity呢,要写多少东西呢,看下图

除去加载假数据的代码,我们写了20行不到,而且这些代码中,全是YzsBaseListActivity强制要求重写的,也就是说,需要你写的代码也就是5到10行,这样的对比你们是否还满意呢,效果是一样的效果,代码量和清晰程度可不一样吧。是不是也想这样写代码,下面就来给大家讲下YzsBaseListActivity是怎么样写的,他的原理是什么。


首先我们在class前进行泛型声明,因为我们要写的是单一列表,所以他们的数据类肯定是一样的,使用泛型声明是为了让我们的adapter知道我们使用了什么数据类,下面的这几个常量就是为列表的布局方式设置的属性,我们在指定位置声明他,列表就是变成我们想要的布局。在这里我要说一下,我们使用的是recyclerview,因为他的功能比listview和gridview更加强大,一个控件就可以写出我们想要的这些布局,他的优化也比list和grid更加的优秀,更加详细的比较大家可以查阅下资料,我建议大家抛弃list和grid,使用最新的技术。


继续向下看,除了上面的常用属性,在initview里,第一个方法就是初始化子布局,这也是强制重写的方法,我们要在这里写出对于recyclerview的所有初始化,接下来,是recyclerview的初始化,同样和前面说的toolbar一样,在xml中使用这个id就可以第三个方法初始化recyclerview的加载形式,这个方法我们是调用不到的,只能用在initItemLayout中对其的值进行设定,放在这里是因为只有recyclerview初始化后才能对其进行操作,下面的判断,判断adapter的子布局是否设定,不舍得抛出异常。下面就是对recyclerview设置adapter了,这个adapter是我写的内部类,所以不需要你去处理,我们直接使用就可以了,


下面的代码,第一个是开启加载更多,这个是baserecyclerviewadapter框架,版本不是最新的,不过这个不影响我们,我会定期提供更新,几乎不需要你们在做神马处理,

下面的这两个方法就是我刚刚提到的,我们在initItemLayout中提供的初始化方法,用我们这个类的静态常量,不要自己瞎写值呀。


这个方法我们也是不需要重写的,这里是对recyclerview的布局形式进行初始化,让他知道我们是怎么设置他的布局形式的。

最后这个Adapter和MyHolder方法,也就是我们缩减adapter的地方,我把他对子布局设置所需变量提取出来,变成强制方法,这样,我们就可以直接在这个方法中对adapter的控件进行控制了,而不用自己去声明出来一个adapter。

以上就是YzsBaseListActivity的所有源码,其实也不是很多,写这种Base其实不难,你只要掌握了这种封装思想,就可以写出比我更好的base了。


YzsBaseHomeActivity

先给大家看下效果图:

这样的首页布局是不是很熟悉,回去点开你的微信,qq,今日头条,爱奇艺看看是不是都是这样的布局,只是有的有下方文字,有的没有,当然,我写的base这些方法必须提供,先不说别的,看看用普通的形式,我们要怎么样书写这种界面。


AndroidFire新闻软件(github开源)

好了,就是这些代码,这个项目的是用mvp架构写的,我发出的这些截图只是在Activity里的代码,有几行代码与这个无关,我们先不用注意,但是你们有没有发现,很多代码重复的在显示隐藏控制着fragment。那我们可不可以省略他呢,当然是可以的,看看我是怎么写这个界面的。

没有了,就这些代码,其实我这样写都是写的多的,为了让你们能看清效果,如果追求最少行数的代码,没有文字的我算上设置Activity布局需要3行,有文字的需要4行,并且自动适配framelayout和viewpager,想想都觉得很激动呢。下面上源码解析。

首先我们要声明出我们所需要的变量,文字数组,图标数组,声明控件名等等,注释里写的很清楚。


接下来呢,我们要声明控件了,吧需要的都声明出来,和上面一样想使用直接在xml中使用它的id就可以了,放在那里随你心情,下面的方法就是初始化tab控件,初始化tab控件里的所需数据,相信看到这里的都应该明白我的套路了,我就是强制你重写这个方法,你能把我怎么样,省的你忘了。如果你不想设置文字,不用管title数据就可以,他就帮你干掉文字了,想使用就去给他赋值,暂时不支持一个有文字一个没文字这样的情况。


这个方法就是对viewpager和framelayout进行判断使用,你提供什么他就用什么,两个都提供了,就用viewpager,比较人性化,但是不建议这样写,因为这样写可能有bug。


下面就是初始化tab控件的对象属性了,把他需要的图标文字fragment放进去。


这个方法注释写的很清楚,初始化fragment,我们在自己写首页切换fragment时,经常会出现重叠现象,但是用了这个base后就不会出现了,其实就是对fragment进行了一些处理,google的lib库在25之前的v4包fragment都有这个bug,但是如果你用25的就不会出现了,我也是用了一个开源库,专门封装了fragment,文章的最后把我用到的这几个开源库都告诉大家。


同样,注释写的很清楚,初始化viewpager的adapter,用framelayout时不会使用这个方法,下面是对viewpager的监听去设置tab的位置。


这两个方法是对导航条进行监听,分别是第一次点击和重复点击方法,如果有需要,自己在里面写你要的方法。


强制重写方法初始化tab,同样,初始化他的方法都写在这里,下面是提供给你的设置和获取fragment的方法。


设置和获取图标文字的方法。

这个是viewpager的adpter内部类,有了他,你也不用去关心viewpager的adapter了,现在还有一些设置导航条的方法没有写在里面,我会继续完善它,控件本来就支持的,我要做的就是把它封装起来,给你们初始化和一些情况的调用,比如导航条理出现小红点,提示数字,这些都是支持的。


以上就是目前YzsBaseHomeActivity的封装了,思想和YzsBaseListActivity一样,就是分模块的强制你在指定方法里做指定的事情,重复的事情交给我来处理,让代码来完成。这些就是我对baseActivity的理解,希望可以帮到大家,抛砖引玉,我相信你们会比我写的更好。


下面是我的项目中用到的第三方开源库

1.FlycoTabLayout——viewpager指示器 与 导航栏控件

2.fragmentation——为”单Activity + 多Fragment”,”多模块Activity + 多Fragment”架构而生,替代官方fragment

3.eventbus——事件总线

4.BaseRecyclerViewAdapterHelper——RecyclerView的强大的BaseAdapter


我的开源项目:

YzsLib

一个共享的开发框架

https://github.com/yaozs/YzsLib

YzsBaseActivity

BaseActivity的框架

https://github.com/yaozs/YzsBaseActivity

今天讲的博客地址:

http://blog.csdn.net/a243981326/article/details/57429927

评论