安卓andbase框架源码解读( 一)

常做开发,怎么能不用框架。框架不仅可以加快我们开发人员的开发效率,还能提高程序的可维护性所以花点时间来学习几个比较优秀的框架还是很有必要的,这样可以省去很多我们去写单调重复的代码的时间,专注功能逻辑的实现,快准狠地开发出优秀的产品。

本人更多的时间是在进行安卓开发,这里选取介绍的框架是andbase,优点这里我就不一一介绍了,不好的话我也不会花时间写博客来介绍它,项目地址:https://github.com/zhaoqp2010/andbase,官方网站http://www.amsoft.cn/post-47.html,里面有展示效果的图片,文档,还有一个apk,可以安到手机上看看效果是不是你想要的,

我觉得效果还是不错,比较符合主流趋势,在github上下载下来之后解压会得到两个项目,一个是源码,一个是demo,其中demo项目要引用源码项目,所以用的时候要将两个一起导入,demo项目会自动去找源码项目这个依赖,找不到的话就会在项目上显示红叉,好,现在都准备好了,让我们开始分析源码吧------〉

AbActivity是整个框架activity的基类,官方是建议activity继承这个类的,这样可以使你的项目有统一的结构,一会我们分析源码的时候我们就会发现,这个类为我们提供了很多常用的视图,比如标题栏titlebar,底部栏,一些进度条,toast,dialog,handler,总之可以让我们省去很多麻烦,当然你可以根据自己的需要再去扩展这个基类,那么作为重中之重,我们这次分析的就是AbActivity类,let‘s go!!!

这个类大约有900行代码,一点点分析是不太现实的,我这里只是捡重点难点来发表一下我的看法,相信弄懂了这些,这个类对你来说就是小case了。

这个类为了兼容较低的api,继承的是FragmentActivity,所以我们以后用的时候自然也可以使用FragmentActivity的属性和方法。

然后看属性,就像我们前面说的,既然这个类为我们提供很多方便的视图,那么自然就得有属性去支持它们,这些属性主要有调试标签TAG,日志开关D,加载进度条 ProgressDialog mProgressDialog;,从底部,中部,上部弹出的Dialog和对应的内容View,应用程序对象abApplication,各种LayoutParams,然后就是界面的结构了,

首先是RelativeLayout ab_base充当总布局,AbTitleBar mAbTitleBar作标题栏布局,AbBottomBar mAbBottomBar 做底部栏布局,RelativeLayout contentLayout做内容布局,

还有一个帧测试的AbMonitorView mAbMonitorView和mMonitorHandler,这两个我们暂时先不说,留到后面再讲,然后就是窗口管理对象WindowManager mWindowManager和它的Params:mMonitorParams,最后还有一个baseHandler,是用来处理发过来的异步消息的

private Handler baseHandler = new Handler() {

		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
				case AbConstant.SHOW_TOAST:
					showToast(msg.getData().getString("Msg"));
					break;
				case AbConstant.SHOW_PROGRESS:
					showProgressDialog(mProgressMessage);
					break;
				case AbConstant.REMOVE_PROGRESS:
					removeProgressDialog();
					break;
				case AbConstant.REMOVE_DIALOGBOTTOM:
					removeDialog(AbConstant.DIALOGBOTTOM);
				case AbConstant.REMOVE_DIALOGCENTER:
					removeDialog(AbConstant.DIALOGCENTER);
				case AbConstant.REMOVE_DIALOGTOP:
					removeDialog(AbConstant.DIALOGTOP);
				default:
					break;
			}
		}
	};

接着看onCreate函数,挑重要的说,

//主标题栏
		mAbTitleBar = new AbTitleBar(this);

		//最外层布局
		ab_base = new RelativeLayout(this);
		ab_base.setBackgroundColor(Color.rgb(255, 255, 255));

		//内容布局
		contentLayout = new RelativeLayout(this);
		contentLayout.setPadding(0, 0, 0, 0);

		//副标题栏
		mAbBottomBar = new AbBottomBar(this);

        //填入View
		ab_base.addView(mAbTitleBar,layoutParamsFW);

		RelativeLayout.LayoutParams layoutParamsFW2 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
		layoutParamsFW2.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
		ab_base.addView(mAbBottomBar, layoutParamsFW2);

		RelativeLayout.LayoutParams layoutParamsFW1 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
		layoutParamsFW1.addRule(RelativeLayout.BELOW, mAbTitleBar.getId()); //跟我们在xml中设置android:layout_below="@id/..."一样
		layoutParamsFW1.addRule(RelativeLayout.ABOVE, mAbBottomBar.getId());
		ab_base.addView(contentLayout, layoutParamsFW1);

这里就是刚才说的在整个布局里添加标题栏,底部栏,和显示的主要内容,因为用的相对布局,而且是在代码中设置的,可能这里看起来比较费劲,尤其是addRule方法,之前不知道,跳到源码中看了看其实就是在LayoutParams中有一个整形数组,属性作为int保存,我们设置的是属性对应的值,就是这个方法

  public void addRule(int verb, int anchor) {
            mRules[verb] = anchor;
        }

然后再挑着往下看,我们平常要用的函数就在这里,包括弹出Toast,设置内容界面,这个有好几个重载的函数,咱们看一个就懂了

public void setAbContentView(View contentView) {
		contentLayout.removeAllViews(); //先将原先的内容清掉
		contentLayout.addView(contentView,layoutParamsFF);//再将新加的布局加到内容中去,
		//ioc
		initIocView();
	}

我们看到这里调用了一个initIocView方法,那么就让我们深入进去,

private void initIocView(){
		Field[] fields = getClass().getDeclaredFields();
		if(fields!=null && fields.length>0){
			for(Field field : fields){
				try {
					field.setAccessible(true);

					if(field.get(this)!= null )
						continue;

					AbIocView viewInject = field.getAnnotation(AbIocView.class);
					if(viewInject!=null){

						int viewId = viewInject.id();
					    field.set(this,findViewById(viewId));

						setListener(field,viewInject.click(),Method.Click);
						setListener(field,viewInject.longClick(),Method.LongClick);
						setListener(field,viewInject.itemClick(),Method.ItemClick);
						setListener(field,viewInject.itemLongClick(),Method.itemLongClick);

						AbIocSelect select = viewInject.select();
						if(!TextUtils.isEmpty(select.selected())){
							setViewSelectListener(field,select.selected(),select.noSelected());
						}

					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

其实就是通过反射让我们可以使用注解来声明view控件,省去繁琐的findviewbyId,比如我们之前要用id为tv_name的textview,要这样写

TextView name;

name = (TextView)(findViewById(R.id.tv_name));

而现在我们只需要用注解声明一下就ok了

@AbIocView(id=R.id.tv_name)
TextView name;

这和很多的注解框架是一样的道理,不过在这里我们就看到了注解底层的实现原理,是不是一下子顿悟了,当然这里用到了反射机制和自定义注解,所以对于一些初学者还是建议先去看看这方面的知识,我们来看AbIocView的源码,就是自定义的注解,

@Target(ElementType.FIELD) //作用于属性
@Retention(RetentionPolicy.RUNTIME) //编译器将annotation存储于class中<span style="color: rgb(103, 102, 21); font-family: ‘Hiragino Sans GB W3‘, ‘Hiragino Sans GB‘, Arial, Helvetica, simsun, u5b8bu4f53; font-size: 16px; line-height: 28px; "> </span>
public @interface AbIocView {
	public int id(); //属性必须,其他可以不指定,因为有默认值
	public String click() default "";
	public String longClick() default "";
	public String itemClick() default "";
	public String itemLongClick() default "";
	public AbIocSelect select() default @AbIocSelect(selected="") ;
}

AbIocSelect类似,大家就自己去看吧就当是巩固上面学到的东西了,然后在刚才的initIocView中有这么个方法setListener,就是根据AbIocView那几个方法设置监听器,相信大家肯定能看懂,这里我就不说了

openMonitor和closeMonitor就先不说了,一般也用不到(其实是我还没有看到那里),再然后就没有然后了吧,ok,今天的分析就到这里,若有错误,敬请提出,大家交流学习,共同进步---〉

睡觉qu,累死了

时间: 2024-10-09 10:01:01

安卓andbase框架源码解读( 一)的相关文章

.NET框架源码解读之SSCLI的调试支持

阅读源码一个比较快的手段就是在调试器里阅读,这样可以在实际运行SSCLI的过程中,通过堆栈跟踪的方式查看完整的程序执行路径. 当在SSCLI环境里执行一个托管程序的时候,堆栈上通常有托管和非托管代码同时在执行.因此在SSCLI里也支持下面几种调试场景: 调试托管程序:在SSCLI里自带了一个托管调试程序,cordbg.exe.跟调试普通.net程序不同,目前还无法在Visual Studio里调试SSCLI环境下的托管程序,在后面有时间的时候,我们会看一下如何在Visual Studio里添加调

ntv.js框架源码解读 - 4navigation.js

4navigation.js源代码: ntv.navigation类,处理页面焦点移动和确认.刷新等操作动作.

安卓图表引擎AChartEngine(六) - 框架源码结构图

包结构: org.achartengine: org.achartengine.model: org.achartengine.renderer: org.achartengine.tools: 安卓图表引擎AChartEngine(一) - 简介 http://blog.csdn.net/lk_blog/article/details/7645509 安卓图表引擎AChartEngine(二) - 示例源码概述和分析 http://blog.csdn.net/lk_blog/article/d

基于Docker的TensorFlow机器学习框架搭建和实例源码解读

概述:基于Docker的TensorFlow机器学习框架搭建和实例源码解读,TensorFlow作为最火热的机器学习框架之一,Docker是的容器,可以很好的结合起来,为机器学习或者科研人员提供便捷的机器学习开发环境,探索人工智能的奥秘,容器随开随用方便快捷.源码解析TensorFlow容器创建和示例程序运行,为热爱机器学者降低学习难度. 默认机器已经装好了Docker(Docker安装和使用可以看我另一篇博文:Ubuntu16.04安装Docker1.12+开发实例+hello world+w

vue源码解读预热-0

vueJS的源码解读 vue源码总共包含约一万行代码量(包括注释)特别感谢作者Evan You开放的源代码,访问地址为Github 代码整体介绍与函数介绍预览 代码模块分析 代码整体思路 总体的分析 从图片中可以看出的为采用IIFE(Immediately-Invoked Function Expression)立即执行的函数表达式的形式进行的代码的编写 常见的几种插件方式: (function(,){}(,))或(function(,){})(,)或!function(){}()等等,其中必有

jdk1.8.0_45源码解读——HashMap的实现

jdk1.8.0_45源码解读——HashMap的实现 一.HashMap概述 HashMap是基于哈希表的Map接口实现的,此实现提供所有可选的映射操作.存储的是<key,value>对的映射,允许多个null值和一个null键.但此类不保证映射的顺序,特别是它不保证该顺序恒久不变.  除了HashMap是非同步以及允许使用null外,HashMap 类与 Hashtable大致相同. 此实现假定哈希函数将元素适当地分布在各桶之间,可为基本操作(get 和 put)提供稳定的性能.迭代col

15、Spark Streaming源码解读之No Receivers彻底思考

在前几期文章里讲了带Receiver的Spark Streaming 应用的相关源码解读,但是现在开发Spark Streaming的应用越来越多的采用No Receivers(Direct Approach)的方式,No Receiver的方式的优势: 1. 更强的控制自由度 2. 语义一致性 其实No Receivers的方式更符合我们读取数据,操作数据的思路的.因为Spark 本身是一个计算框架,他底层会有数据来源,如果没有Receivers,我们直接操作数据来源,这其实是一种更自然的方式

Apache Beam WordCount编程实战及源码解读

概述:Apache Beam WordCount编程实战及源码解读,并通过intellij IDEA和terminal两种方式调试运行WordCount程序,Apache Beam对大数据的批处理和流处理,提供一套先进的统一的编程模型,并可以运行大数据处理引擎上.完整项目Github源码 负责公司大数据处理相关架构,但是具有多样性,极大的增加了开发成本,急需统一编程处理,Apache Beam,一处编程,处处运行,故将折腾成果分享出来. 1.Apache Beam编程实战–前言,Apache B

精通Spark:Spark内核剖析、源码解读、性能优化和商业案例实战

这是世界上第一个Spark内核高端课程: 1, 该课程在对Spark的13个不同版本源码彻底研究基础之上提炼而成: 2, 课程涵盖Spark所有内核精髓的剖析: 3, 课程中有大量的核心源码解读: 4, 全景展示Spark商业案例下规划.部署.开发.管理技术: 5, 涵盖Spark核心优化技巧 该课程是Spark的高端课程,其前置课程是“18小时内掌握Spark:把云计算大数据速度提高100倍以上!”. 培训对象 1,  系统架构师.系统分析师.高级程序员.资深开发人员: 2, 牵涉到大数据处理