TinyOS应用程序缺陷及其benchmark库的研究
- 这是我的毕业设计课题,我毕业设计的话跟导师申请的国家自然科学基金项目《传感网程序并发错误的检测》有关。
- 首先简单介绍一下这个题目吧
1、TinyOS是专门针对嵌入式无线传感器网络设计的操作系统,TinyOS操作系统它本身也是一种无线传感网程序。
2、benchmark的直接翻译过来的意思是“标准的检测程序”,在软件测试范畴里面可以简单理解成“含有缺陷的被测程序”,通过执行benchmark库里面被测程序,可以显示出相应的bug。
3、传感网程序它是基于nesC语言编写的,一种扩展的C语言;
4、Avrora它是一个执行无线传感网程序的模拟器,这种模拟器能够捕获传感网程序的动态执行行为。 - 所以毕业设计《TinyOS应用程序缺陷及其benchmark库的研究》涉及到的主要工作是:通过Avrora模拟器捕获传感网程序的动态执行行为,分析TinyOS程序的bug,并且提取出这些bug的特征模式,然后编写出含有这些bug特征模式的被测程序,最后添加到benchmark库里面,通过执行benchmark库中的被测程序能够可以显示出相应的bug。
新浪微博客户端的实现
Android Animation:
Android里面提供了Animation类来实现相应的动画效果。
举个例子来说吧:
1. 一般一个APP启动的时候,会有一个欢迎界面,可以为这个欢迎界面设置alpha 透明度渐变的动画效果。我记得实现的流程是:
1、new出一个透明度渐变的Animation对象,并且设置它透明度渐变的值(1代表完全可见、0代表不可见)
2、第二步的话为这个Animation设置持续时间
3、最后的话为这个Animation设置监听,也就是当Animation动画结束的时候跳转到登录界面
2. 好像也可以在xml文件里面设置Animation动画效果,还有刷新的那个小图标也涉及到旋转的Animation。
//formAlpha:动画起始透明度
//toAlpha:动画结束时透明度,值均为0.0(完全透明)——1.0(完全不透明)
//duration:动画的持续时间
//为动画设置相应的监听
AlphaAnimation animation = new AlphaAnimation(0.0f, 1.0f);
animation.setDuration(3000);
imageLogo.setAnimation(animation);
animation.setAnimationListener(new AnimationListener();//动画结束的时候跳转到登录界面
新浪微博客户端实现的系统框架
- 新浪微博客户端实现的系统框架也是采用的MVC模式的。
1、视图层的话包含了一个个的Activity,用于与用户交互的界面,每一个Activity中都会实现两个抽象方法:一个是初始化Activity的init方法、还有一个是执行某项操作更新Activity的refresh方法。
2、控制层,主要的业务逻辑是在这一层实现的,我记得有一个核心类(MainService)它既是一个运行在后台的Service类,也是一个线程类。它里面维护的两个比较重要的存储结构,一个是任务队列,另一个是要更新的Activity的ArrayList。也就是说用户在Activity上的操作都会对应于一个个的任务,添加到任务队列里面。然后MainService会开启线程访问网络调用相应的API,最后通过Handler将子线程的处理结果返回跟主线程,并且跟新UI。
3、模型成的话就设计到一些bean存储对象啊还有一些访问数据的操作。
OAuth2.0授权认证
实现新浪微博OAuth2.0授权认证并不难,新浪微博SDK里面就提供好了实现授权的demo,仿照这个demo来写就行了。
OAuth2.0授权认证总的来说就是新浪微博允许用户提供了一个自己的AccessToken,第三方应用根据这个AccessToken就能访问新浪微博资源服务器上这个用户的信息了。
新浪微博OAuth2.0授权认证过程就是:
1、先在新浪微博开发者平台创建一个应用,新浪服务器认为这个创建的应用合法的话就给这个应用分配一个app key
2、第三方应用获取到app key之后,进入新浪微博的授权界面,一个WebView
3、在授权界面中输入用户名的账号和密码,同意给这个第三方应用授权之后,资源服务器会根据app key和用户信息给第三方应用分配一个AccessToken。
4、第三方应用获取这个AccessToken之后,就能通过微博提供的API访问微博服务器用户的特定信息了。
SQLite数据库
- Android里面内嵌了一个很小的、基于文本的关系型轻量级数据库SQLite
- SQLite中两种不同类型的数据库:readerDatabase、WriterDatabase。也就是说如果只涉及到查询操作的话直接使用readerDatabase数据库就好了,如果涉及到添加、删除、修改的话就要使用WriterDatabase数据库。
- 在使用SQLite的时候也会有相应的回调方法,譬如说第一次创建数据库的时候会调用onCreate方法,之后的话只要打开数据库就行了。还有跟新的时候也会调用onUpgrade回调方法。
- 也可以将SQLite数据库导出来,用navicat这个可视化工具来查看。
SharedPreference
- SharedPreference实际上是一种基于XML形式的的文件存储方式,存储数据的形式是“key-value”键值对。通常用sharedPreference来存储程序的一些配置信息。
- SharedPreference本身只能获取数据,不支持存储和修改。也就是说如果要存储和修改数据的话就要通过Editor对象来实现。
- 数据的存储步骤我记得是:
1、获取SharedPreference对象;
2、根据SharedPreference获取Editor对象;
3、调用Editor对象的putXXX()方法,存储key-value键值对信息;或者通过Editor对象的getXXX(key)方法获取value的信息。
4、通过Editor的commit()方法将数据提交到SharedPreference内。
File存储
- Android里面的文件存储跟Java中文件存储差不多吧,都是获得一个文件的输入输出流对象,利用这个输入输出流对象对文件进行读写操作。然后里面会涉及到一种设计模式:装饰模式
- 文件存储的特点就是能够存储大量的数据,但是我们都知道对文件的读写也是种比较耗时的操作。
ContentProvider
- ContentProvider主要有两个重要作用
1、第一个的话实现了不同应用程序之间的数据共享;
2、第二个话是为共享数据提供了一个统一的访问接口:URI
也就是可以将ContentProvider简单理解成:应用程序将自己要共享的数据放到ContentProvider里面去,其它应用程序可以通过ContentProvider提供的接口来访问里面的数据来实现共享。 - 譬如说我们的手机联系人信息、一些视频音频信息都是通过ContentProvider向外暴露自己的共享数据的。
- ContentProvider中数据存储的方式也可以简单理解成是一张表的形式,可以通过重写相应的增、删、改、查来操作共享数据。
- ContentProvider实现应用程序之间的数据共享底层机制我记得是:Binder进程间的通信机制还有共享内存机制相结合。
ListView加载数据
- ListView的使用
1、ListView使用的话会涉及到三个元素吧
①、第一个是ListView对象,以及定义ListView中Item的布局对象;
②、第二的话是要在每一个Item上显示的数据源
③、还有一个就是将数据源中的数据绑定到每一个Item上的数据适配器,譬如说数组适配器啊(ArrayAdapter)、SimpleAdapter啊、还有一个我们用得最多的BaseAdapter
有了这三个元素之后就可以实现将我们想要的数据显示到ListView上了。 - ListView加载数据的实现原理及优化
1、ListView数据加载的实现原理:
如果我们每显现一个Item都要创建一个Item对象的话肯定是不行的,假如有上万条Item数据,每次都要创建Item对象的话肯定是会内存溢出的。
2、ListView底层的话会有一个Recycler构建,里面会维护一个ConvertView缓存变量。
3、假如一开始ListView上可见的Item项是10个,那么这10个Item在内存里面都会被创建对象,之后ListView向上滑动,如果刚好Item1完全不可见的时候,就会把一开始创建好的Item对象缓存到Recycler构建里面,并且赋值给ConvertView对象
4、之后第11个Item完全可见的时候,就不需要重新创建Item对象,而是直接引用ConvertView这个对象就好了。
5、也就是说即使有成千上万条的Item数据,内存里面只有屏幕可见条数量的Item的对象。
6、之后我们我们比较常见的一个ListView数据加载优化的话是使用ViewHolder这个静态类。平时我们用的findViewById方法返回每一个Item中控件对象其实是一次文件的读写操作,文件读写呢,又是很耗时的操作。第一次的话我们是要用findViewByID方法,之后的话就可以将这些数据保存在ViewHolder这个静态类里面,这样下次再使用Item中控件的时候就不用再调用findViewById这个方法了。
ListView异步加载和缓存图片(ImageLoader)
- ListView异步加载和缓存图片用的比较多的一个开源软件是ImageLoader,做那个新浪微博客户端项目的时候有分析过ImageLoader的源码,然后照着这个思想实现过自己的一个简单的ImageLoader。
- ImageLoader使用的话还是挺简单的,就是在获取图片之前,先设置一下图片加载和缓存的一些配置信息,譬如说设置一下内存缓存啊、图片缓存啊、线程池啊以及图片正在加载过程中显示的图片、加载失败的图片显示啊这些。
- 这些配置信息设置好以后就可以调用displayImage方法根据传入的图片url参数获取图片并显示在相应的控件上了。
- 接下来讲一下ImageLoader异步加载和缓存图片的一个大致流程吧
1、首先根据URL从内存缓存中找,如果内存缓存中有该URL对应的BitMap的话就直接返回
2、没有的话在从文件缓存中查找这个URL对应的图片,有的话就返回图片并且将图片保存在内存缓存里面。
3、如果缓存中都没有图片的话就会开启线程访问网络,将获取的图片通过handler返回给主线程,更新UI。同时将图片信息保存到内存缓存和文件缓存里面。 - 我记得ImageLoader中默认使用的内存缓存是LruMemoryCache,最近最少使用的内存缓存,也就是说当缓存中内存不够的时候就会替换出缓存中最近最少使用的图片,LruMemoryCache底层实现我记的是LinkedHashMap,里面保存的是BitMap对象的强引用,而且实现了最近最少使用这个算法。
- 当然还有其他缓存策略,譬如说FIFO缓存策略我啊,超过一定时间的缓存策略啊。
Java线程池
我们通过new Thread方式创建线程是有一定缺陷的,譬如说:
1、每个线程会占据大概1M的内存,开启的线程过多的话很有可能会导致内存溢出
2、还有一个就是缺乏对线程的统一的管理,这样就可能造成过多的线程并发执行、访问临界资源导致拥塞的情况。引入线程池的话
1、第一个他可以重用线程池里面已经创建了的线程,减少内存的消耗;
2、另外一个它对线程的并发数目有一个统一的管理,防止过多的并发的线程并发执行、访问临界资源而导致拥塞的情况。- android里面提供了四种类型的线程池
1、newCachedThreadPool:可缓存的线程池,这种线程池的特点就是如果任务少,就会释放线程池中空闲的对象;如果任务多,就会在线程池中创建新的线程执行任务。
2、newFixedThreadPool :固定大小的线程池,创建的线程对象达到给定的值之后就不会再创建新的线程了。这种类型的线程池能够有效地控制线程的并发执行。
3、newScheduledThreadPool: 定长线程池,支持定时及周期性任务执行。
4、newSingleThreadExecutor:单一的线程池。这个线程池只有一个线程对象,也就是相当于单线程串行执行任务。 - 每一种线程池呢又会配合着相应的任务队列一起使用,而且JDK帮助文档里面有句原话就是强烈建议使用这四种线程池,而不要自己去定制。
Handler线程通信
- Android里面有两种类型的线程、一种是MainThread、还有一种是WorkThread。
- MainThread主要负责的工作是通过界面完成与用户交互的事;workThread的话主要是用来处理一些比较耗时的操作,譬如说访问网络的操作啊、文件读写操作啊。
- 而且Android里面这样一个准则,就是在原则WorkerThread是不允许更新UI的,更新UI操作的话只能在MainThread里面。这就会涉及到WorkThread与MainThread进程通信问题。
- Handler、looper和MessageQueue三者构成了Android里面线程间最重要的消息传递以及消息处理机制。
Handler层实现原理概括起来就是:
Looper.prepare()创建Looper对象和MessageQueue对象,通过一个ThreadLocal线程本地变量将三者关联起来;创建Handler对象通过obtainMessage()获得消息对象,并将消息对象放到MessageQueue中;最后,Looper.loop()方法死循环从消息队列中获取Message并调用Handler的handleMessage处理。
TextView中字体的样式显示以及字体的图片显示
- 一般来说在Android TextView控件上显示的文字是没有样式的,但是有些问题有需要有样式,譬如说一些标题啊、姓名啊、URL啊这些文本信息的高亮显示。
- 为TextView设置字体样式可以根据正则表达式还有Spannable对象来实现。
就拿高亮这个例子来说吧: - 首先根据正则表达式查找出要高亮的文字,保存在一个ListView里面,之后遍历ListView,通过Spannable实例来为字体设置高亮。
图片的放大缩小
Android里面提供了Matrix类来对图片的滑动啊、旋转啊、缩放处理。
- 图片滑动
1、为图片设置的点击事件监听还有活动事件监听,
2、点击的时候记录初始的点击坐标,滑动之后记录滑动后的坐标
3、根据计算的滑动距离修改Matrix对象;最后通过Matrix对象重新设置图片。 - 多点触控放大图片
1、为图片设置的双点击事件监听还有滑动事件监听,
2、点击的时候记录初始的点击坐标,滑动之后记录滑动后的坐标
3、根据计算的滑动距离修改Matrix对象;最后通过Matrix对象重新设置图片。。
ListView加载更多及分页显示
就拿好友动态分页显示来说吧:
- 每一条好友动态里面都有一个序列号字段,用来标识这条动态发表的先后次序。
- 一开始的时候会加载指定数量的好友动态保存到ArrayList这个数据源里面,通过这个ArrayList数据源设置每一个Item的信息。假设加载了20条数据。然后也获得了第20条好友动态的一个序列号。
- 当滑动到ListVeiw底部,点击“加载更多”的时候会开启线程、访问网络获取第20条动态之后、指定书目的好友动态,通过Handler返回数据保存在一开始的ArrayList数据源里面。这个时候因为ArrayList添加了新的数据,记得要调用notify方法通知Adapter数据源发生了改变。这样的话就能显示40条的好友动态数据了;
不过为了要有刷新的效果,最后一个显示的Item应该为第21个。
ListVeiw下拉刷新
我记得微博客户端项目的刷新方式我定义了两种,一种是点击按钮刷新方式;另一种是下拉刷新方式。点击按钮刷新的实现方式比较简单:就是点击按钮,开启线程、访问网络、获取最新指定数目的好友动态,保存在ArrayList里面,通过Handler返回给主线程,更新ListView即刷新成功
- 还有一种就是下拉刷新方式
1、下拉刷新涉及到Android里面自定义控件的知识,首先自定义一个ListView继承ListView,为它添加一个下拉刷新的头控件、还有一个加载更多的尾控件。初始情况下这个下拉刷新的头控件的高度为0。
2、然后重写onTouchEvent方法,针对onTouchEvent每一种动作执行不同的操作
譬如说:
①:一开始点击动作的时候记录初始的Y轴坐标
②、下拉动作的话会不断改变和计算头控件的高度,当手指抬起并且下拉刷新的布局大一某一指定值的时候,执行刷新操作;
③、然后执行的操作也就是开启线程、访问网络、获取最新指定数目的好友动态,保存在ArrayList里面,通过Handler返回给主线程,更新ListView。
④、刷新成功之后设置从ListView的第一个Item开始显示。
Java群聊系统
java群聊系统涉及到的线程主要有三类:服务器端负责连接的线程 + 服务器与客户端通讯的线程 + 客户端与服务器通讯的线程。
- 服务器端创建一个绑定到特定端口的ServerSocket对象,并且启动线程死循环监听客户端的连接。
- 客户端的话会根据服务器的主机ip和端口号创建一个Socket对象,启动线程连接到指定的服务器
- 连接成功后,服务端又会创建专门与客户端通信的线程。所以服务端的话会涉及到HashMap这样一个存储结构,HashMap的key是一个个与服务器连接了的用户,value的话是专门负责与这个用户进行通信的线程。
- 然后通信的内容主要涉及到三个方面的:登录成功后用户在线列表的更新、用户的群聊信息还有程序的退出后用户在线列表的更新。然后通信的数据类型采用的是XML格式的数据。
- 就拿用户成功登陆群聊系统以后用户在线列表的跟新来说吧:用户在线列表的更新:用户登录成功以后,会把用户基本信息封装成XML格式的数据,发送给服务端,服务端接收到这个XML数据之后解析出用户名,把这个新登录的用户添加到HashMap这个用户在线列表中;之后遍历整个HashMap,将新的在线的用户又封装成XML数据发送给每一个客户端显示。
动物识别系统
动物识别系统的实现呢主要是依赖于这个产生式搜索算法。
基于产生式搜索算法实现的动物识别系统主要涉及到
- 首先规则库的建立,规则库的话就是就是一些由条件以及结论组合而成的规则,譬如说能推出是斑马的一些列规则就是:如果动物能产奶、就能推出是哺乳动物;如果动物是哺乳动物而且能反刍,就能推出是蹄类动物;如果动物是蹄类动物而且它有黑白相间的条纹能推出该动物是斑马
- 然后根据用户输入的事实根据产生式搜索算法与初始化的规则库进行比较,得出相应的结论。
- 产生式搜索算法属于人工智能里面的启发式搜索算法,是一种自学习的算法。总得来说它的做法就是根据条件推理出结论,然后将结论又作为新的条件条件到规则库里面,进一步推出新的结论。
你在项目过程中遇到的难点以及相应的解决方式
- 在实现新浪微博客户端好友微博列表显示功能模块,里面涉及到一个Android比较重要的知识点,ListView异步加载和缓存图片。
- 一开始实现这个ListView异步加载和缓存图片是参照网上的一些demo程序,这些demo程序应用到微博项目里面的话,加载少量微博动态图片的话是没有问题的,都能正常显示,但是如果加载的图片多了的话就总会报OOM,内存溢出这个错误。然后我就在那里死磕Android如何解决OOM这个问题。
- 后面的话还是带我们项目实习的那个老师给我们推荐了一个ListView异步加载和缓存图片的开源软件ImageLoader。
- ImageLoader使用起来的话还是挺简单的,就是在获取图片之前,先设置一下图片加载的缓存信息,譬如说配置一下内存缓存啊、文件缓存啊、线程池啊。这些配置信息设置好以后就可以调用displayImage方法根据图片url参数获取相应图片并显示在相应的控件上了。
- 之后的话我又仔细地研究了下ImageLoader开源项目的源码,然后照着ImageLoader的思想自己实现了一个简单版的ImageLoader,功能的话虽然没有ImageLoader那么强大,但ImageLoader的基本功能也还是有的,也了解了异步加载和缓存图片的一个底层实现原理。
评价一下自己的优缺点
- 优点:
1、我认为自己一个比较好的优点就是别人交给我做的任务,或者是我答应帮别人做的事情,我就一定会尽全力去完成,我觉得这样的人会比较有魅力吧,身边的人都觉得我是一个很靠谱的人吧,也正是因为这样他们也都挺愿意跟我打交道吧;
2、还有一个就是在做一件重要事情之前,我会做好充分准备,我喜欢把那些可预见的事情做好,将事情的发展啊控制在自己所能控制的范围之内,并且会把目标定的比较高,这样的话第一个能让自己全力以赴,第二个会取得比预期要好的结果。 - 缺点
1、缺点的话我算是一个比较内向的人吧,在有很多人的大场合下我一般不会主动发言表态;
2、还有一个就是我做事有的时候会很容易陷入到细节问题里面去,
职业规划
- 我以后还是打算做技术方面的工作吧,然后对Android开发挺感兴趣的,校招过程中投递的岗位也是跟Android开发相关的。
- 我的一个简单的职业规划呢是在一开始的一两年里面多做一些Android项目,积累经验,争取在尽可能短的时间内能肚子hold住一个完整的Android项目。
- 之后的话可能会根据公司提供的职位竞升通道,譬如说Android程序员到、高级工程师、Android架构师、项目经理,CEO,这些职位一步一步奋斗。
- 之后的话我回去学IOS。