2015/03/16 星期一
计划:
- 毕业设计的方案确定
- 开始进行客户端开发
完成:
- 简单Android客户端灯具控制,包括两个开关和一个图片开关,具体接口需要应用时再设定。
- 简单html5混合应用,仅有一个图片开关。HTML5中没有现成的开关可用,网上多利用CSS将checkbox改造为开关按钮,使用时需要搞清楚位置、属性等设置。
2015/03/17 星期二
计划:
- 现在所开发的程序不能保存设定数据,查找资料解决设置信息保存的问题。
- 学习Android开发所需知识。
完成:
- 虚拟机出现问题:parseSdkContent failed java.lang.ExceptionInInitializerError没解决,不过还能用。
- 使用SharedPreferences解决配置信息保存问题。
2015/03/18 星期三
计划:
- 真机调试前两天开发的测试应用。
- 设计移动客户端方案,包括页面和逻辑。
完成:
- 花了一上午时间,豌豆荚、91手机助手、乐助手等都没有解决真机连接电脑无法安装驱动的问题,纠结。
- 还好下午用百度手机助手解决了。然后因为手机是android4.1的,而测试应用的最低版本为4.4,又新建了一个应用,拷贝代码才调试成功。
- 准备晚上与老师讨论的资料,即设计android客户端的页面方案。
参考资料:
在物联传感的这个活动中,活动一期就是智能照明的管理。
从物联传感所给出的套餐上看,这套智能照明设备相当精简,主要包括的内容也只有8个智能开关和1个智能网关,其中智能开关中有5个一键智能开关、1个两键智能开关、1个三开关和1个6路场景开关。套餐中并没有出现智能灯泡、智能插座等其他智能照明相关的设备。也就是说,要完成智能照明的体验,只需要这几个智能开关和一个智能网关就行了,根本没有想得那种复杂。可有有人会怀疑,只靠这几个小玩意儿所达到的效果会不会不好呀?其实同样有趣。
最有趣的玩法
在介绍这套智能照明的有趣玩法之前,先大致了解一下它们的主要功能。智能开关属于智能家居中的控制节点,能够控制家里的灯泡和智能灯泡,它主要有四大功是远程、联动、定时和场景。远程就是用户无论在何时何地,都能利用手机来控制智能开关,进而控制由开关控制的灯泡;联动则是对绑定设备功能的触发,操控一个开关,与其绑定的开关也会触发功能,并实现对其所控制的灯泡的开关;定时功能是根据用户的生活习惯对某些开关进行定时,在特定的时间触发开关功能;场景功能则是将开关编不定的场景模式,实现一键控制。
从上面的几个功能可以得知,这个套餐的玩法简单,但也不失趣味性,主要在于它是可以让用户自己来DIY的。这些开关都是可以通过远程和本地两地两种方式来控制的,在家可直接按键开关,在外则可以用智能气机或ipad开关,而DIY的部分在于控制哪几开关,都由用户来决定。例如,哪些进行统一编组设定为“离家”、“回家”、“起夜”等场景都由用户根据家庭实际情况来决定,编组成功后,出门时按下“离家”即可。另外,设定场景后还允许用户再编辑,可自由删除或增加其他智能设备。
2015/03/19 星期四
计划:
- 根据昨天的设计,继续场景相关的页面,计划一天一个页面。
- 学习《疯狂Android讲义》基础知识。
完成:
- 旋转屏幕时,程序被杀死重新调用,以后要考虑到这种情况。
- ListView组件的使用,结合网上和书上的代码,进行列表项的编写和测试。
- 布局问题:开关与标题不在同一行。
参考资料:android ListView详解
2015/03/20 星期五
计划:
- 查找布局方面的资料,解决布局问题。
- 编写页面下面的选项卡控件,底部菜单栏。
完成:
- 整体使用RelativeLayout相对布局,每个List内使用LinearLayout线性布局和开关空间。
- 使用SimpleAdapter填充ListView。
- 网上找到一个底部菜单栏Demo,很合适,不过还没搞懂。
2015/03/23 星期一
计划:
- 理解底部菜单栏Demo,尝试改造成自己想要的样式。
完成:
- 测试和改造了Fragment生成底部菜单栏,但是此处继承的是FragmentActivity,分页面继承的是Fragment,因此无法使用ListActivity。
- 需要改造成主页面继承Activity,分页面继承Fragment,然后再在分页面中实现列表控件。
2015/03/24 星期二
计划:
- 继续研究使用Fragment和RadioGroup生成底部菜单栏,继承Activity而不是其他的。
- 阅读分析Fragment官方文档。
完成:
- 实现了底部菜单栏的分页面显示,但是布局仍然有问题。
- Fragment的基本函数功能和使用已经了解。
2015/03/25 星期三
计划:
- 继续解决底部菜单栏多个页面之间独立显示问题
- 将列表控件集成到底部菜单栏中。
完成:
- 实现了底部菜单栏各个页面之间独立显示,并解决布局问题。之前的布局问题出在main.xml文件中,多个<fragment>标签占据很多空间,导致布局显示不正常,解决办法为只保留一个<fragment>标签,各个分页面要显示时都在这个标签中显示。
- 将底部菜单栏和列表页面结合成功,不过显示时有一些小问题,开关控件在布局文件中先显示出来了一个,需要想办法去除。另外此处继承的是ListFragment而不是Fragment,是否会对将来添加其他控件产生影响还不知道。
在Fragment中使用ListView的时候,需要使用适配器,在调用SimpleAdapter的时候,传递的参数需要注意。首先看SimpleAdapter的函数定义
SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
参数:
1,context:上下文。
2,data:基于Map的list。Data里边的每一项都和 ListView里边的每一项对应。Data里边的每一项都是一个Map类型,这个Map类里边包含了ListView每一行需要的数据。
3,resource :就是一个布局layout,可引用系统提供的,也可以自定义。
4,from:这是个名字数组,每个名字是为了在 ArrayList数组的每一个item索引Map<String,Object>的Object用的。即 map 中得key值
5,to:里面是一个TextView数组。这些 TextView是以id的形式来表示的。例如:Android.R.id.text1,这个text1在layout当中是可以索引的。
一般上下文context使用this指针,但是在Fragment中会报错,需要使用如下的方式进行调用。
SimpleAdapter listItemAdapter=new SimpleAdapter(
getActivity(), //这里要使用此,这样才不会报错。
listItem,
R.layout.fr_events_grid,
new String[]{"ItemTitle","ItemMessage","ItemImage"},
new int[]{R.id.fr_events_list_empty_view_title,R.id.fr_events_list_empty_view_message,R.id.fr_events_list_empty_view_image_view}
);
listView.setAdapter(listItemAdapter);
2015/03/26 星期四
计划:
- 优化列表显示控件。
- 开发场景页面。
- 考虑画面设计、各个页面的逻辑和功能等问题,如节点页面中按钮的反应,节点的存储等。
- ListView中开关的点击事件监听。
- 改变List的存储结构(数据库或者其他),读取方式。
- 添加编辑功能(增删改)。
完成:
- 解决列表控件重叠问题:重叠的原因是Fragment的onCreateView方法中首先要之指明引用的layout资源文件,若直接将列表控件的布局文件(包括两个textview和一个stwich)作为它的引用文件,则会在页面上生成一个按钮控件,这个按钮与后来列表生成的按钮不在同一层。解决办法为将列表的布局文件单独写一个layout文件,只在列表生成时SimpleAdapter方法中引用。
- 利用节点页面的源码改造生成了场景列表。
- 之前的列表文件是用SimpleAdapter方法生成的,但是考虑到之后还要涉及按钮事件监听,在周路学长的建议下改为使用BaseAdapter方法。把网上查到的资料稍微改造,就顺利的实现了继承BaseAdapter类的列表显示,而且也完成了列表中按钮的监听。但是具体代码的实现原理并没有太理解,还需要找几个例子测试,理解一下,不能就这样似懂非懂就算了。
参考资料:【转】Android之自定义Adapter的ListView
2015/03/27 星期五
计划:
- (上午)理解BaseAdapter的实现原理,测试书上和网上的例子。
- 改变List的存储结构(数据库或者其他),读取方式。
- 添加编辑功能(增删改)。
- 按钮/开关的状态信息保存。
完成:
- 完成BaseAdapter资料的查找和整理,对它的使用有了进一步的了解。
- 添加了全部打开和全部关闭两个按钮,但具体的功能实现并没有做,准备在完成数据库存储之后再实现。
BaseAdapter 详解:
BaseAdapter适配器里有个getView()需要重写
public View
getView(int position,View converView,ViewGroup parent)
{
//略 }
int position位置,一般BaseAdapter都是很多类型一样的数据展示在界面,该属性是判断显示在界面上的是第几个,通过position在BaseAdapter自定义的数组或者集合中取值。并展示在界面上。
View converView 展示界面上的一个item。因为手机屏幕就那么大,所以一次展示给用户看见的内容是固定的,如果你List中有1000条数据,不应该new1000个converView,那样内存肯定不足,应该学会控件重用,滑出屏幕的converView就在下面新进来的item中重新使用,只是修改下他展示的值。
ViewGroup parent 这个属性是加载xml视图时使用。
代码如下:
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
holder=new ViewHolder();
convertView = mInflater.inflate(R.layout.list_node, null);
holder.title = (TextView)convertView.findViewById(R.id.title_node);
holder.info = (TextView)convertView.findViewById(R.id.info_node);
holder.switch1 = (Switch)convertView.findViewById(R.id.switch_node);
convertView.setTag(holder); //.setTag(holder); 传入ViewHolder对象,用于缓存要显示的数据,可以实现异步加载
}else {
holder = (ViewHolder)convertView.getTag();
}
convertView = mInflater.inflate(R.layout.list_node, null);确定父控件,减少宽高的测算
这里的convertView是最关键的部分,原理上讲 当ListView滑动的过程中会有item被滑出屏幕而不再被使用, 这时候Android会回收这个条目的view ,这个view也就是这里的convertView
当item1被移除屏幕时,我们会重新new一个View给新显示的item_new, 而如果使用了这个convertView 我们可以复用它,这样就省去了new View的大量开销.
if(convertView != null)这句判断必须要,第一次创建listview时,convertView是为null的,所以为空的时候就把解析出来的view 赋值给convertview,然后你下滑列表的时候,convertview就不为null,就可以直接调用了.
工作原理:
- ListView 针对List中每个item,要求 adapter “给我一个视图” (getView)。
- 一个新的视图被返回并显示
如果我们有上亿个项目要显示怎么办?为每个项目创建一个新视图?NO!这不可能!
实际上Android为你缓存了视图。
Android中有个叫做Recycler的构件,下图是他的工作原理:
- 如果你有10亿个项目(item),其中只有可见的项目存在内存中,其他的在Recycler中。
- ListView先请求一个type1视图(getView)然后请求其他可见的项目。convertView在getView中是空(null)的。
- 当item1滚出屏幕,并且一个新的项目从屏幕低端上来时,ListView再请求一个type1视图。convertView此时不是空值了,它的值是item1。你只需设定新的数据然后返回convertView,不必重新创建一个视图。
问题:
一.View
getview(int position, View convertview,
ViewGroup parent )中的第二个参数是什么含义;
二.View的SetTag和getTag方法的用途;
解答:
convertview的机制是在初始显示时,每次显示一个item都调用一次getview方法,但是每次调用的时候covertview为空(因为还没有旧的view),当显示完了之后。如果屏幕移动了之后,并且导致有些Item(也可以说是view)跑到屏幕外面,此时如果还有新的item需要产生,则这些item显示时调用的getview方法中的convertview参数就不是null,而是那些移出屏幕的view(旧view),我们所要做的就是将需要显示的item填充到这些回收的view(旧view)中去,最后注意convertview为null的不仅仅是初始显示的那些item,还有一些是已经开始移入屏幕但是还没有view被回收的那些item。
view的setTag和getTag方法其实很简单,在实际编写代码的时候一个view不仅仅是为了显示一些字符串、图片等控件,有时我们还需要他们携带一些其他的数据以便我们对该view的识别或者其他操作。于是android 的设计者们就创造了setTag(Object)方法来存放一些控件或数据来和view绑定,我们可以理解为这个是view 的标签也可以理解为view 作为一个容器存放了一些控件或数据。而这些控件或数据我们也可以通过getTag() 方法来取出来。
参考:
[Android] ListView中getView的原理+如何在ListView中放置多个item
BaseAdapter中重写getview的心得以及发现convertView回收的机制
PullToRefresh使用详解(一)--构建下拉刷新的listView
PullToRefresh使用详解(二)---重写BaseAdapter实现复杂XML下拉刷新
2015/03/30 星期一
计划:
- 改变List的存储结构(数据库或者其他),读取方式。
- 添加编辑功能(增删改)。
- 按钮/开关的状态信息保存。
- 全开全关按钮的边界。
完成:
- 查找数据库存储相关资料,包括使用SQL语句直接操作SQLite数据库和使用SQLiteOpenHelper类两种方式。
- 边看边改边测试,有进展,但还没有成功:能够读取数据库的资料,但是还不能写入。
参考:
Android中ListView,SQLite,BaseAdapter的结合
android数据库储方式(一)----SQLite的基本操作