黑马程序员:三大框架Struts2-day01笔记
第1章 框架概述
什么是框架,为什么使用框架,框架优点
框架(framework)是一个基本概念上的结构,用于去解决或者处理复杂的问题
框架,即framework。其实就是某种应用的半成品,就是一组组件,供你选用完成你自己的系统。简单说就是使用别人搭好的舞台,你来做表演。框架是在特定的领域内解决问题。优点
重用代码大大增加,软件生产效率和质量也得到了提高
使用框架开发,它提供统一的标准,大大降低了我们的后期维护。学习框架重点:了解框架做了什么,我们要在这个基础上在做什么事情。
第2章 java开发中常用框架
SSH
(SSM SSI)SSH struts2 spring hibernate SSM(SSI)springmvc spring mybatis(ibatis)
SSH 它是企业开发中比较主流的一套架构。SSH框架在开发中所处的位置:
黑马程序员郑州中心 编著
第3章 Struts2框架介绍
什么是struts2框架,学习struts2框架的核心。
Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互
Struts2=struts1+webwork
问题:struts2是一个mvc框架,它的mvc是什么?
javaweb开发中的mvc,是在jsp的model2模式中提过 Model------javabean View--------jsp Controller----servlet
黑马程序员郑州中心 编著
核心点: 1.拦截器 interceptor 2.Action 3.ognl与valueStack
在现在开发中与struts2比较类似的框架有哪些? Struts1 webwork springmvc jsf
Struts2框架流程
黑马程序员郑州中心 编著
第4章 今天内容介绍与重点
今天内容:
一个简单的登录案例
在这个案例中,我们要使用struts2框架怎样解决
重点: 1.struts2框架如何完成原来由servlet完成的工作。2.Struts2框架如何完成请求参数的封装处理 3.Struts2框架如何完成页面跳转。
黑马程序员郑州中心 编著
第5章 简单登录案例原型
需要三个jsp页面
login.jsp
success.jsp failer.jsp 还需要一个servlet
LoginServlet 主要完成的是业务逻辑操作。
login.jsp
LoginServlet
黑马程序员郑州中心 编著
第6章 Struts2框架来完成登录操作
6.1 问题:为什么使用struts2框架?
Struts2框架它是一个在web中应用的mvc框架。我们使用strtus2框架来完成web开发有什么优势?
6.2 问题:怎样使用strtuts2框架
首先要上网下载它的jar包。步骤: 1.导入相关的jar文件
2.需要在web.xml文件中配置一个Filter(只有配置了它才可以使用struts2框架)
黑马程序员郑州中心 编著
3.struts.xml配置
4.创建Action来完成逻辑操作
6.3 快速入门
我们使用的是struts2 2.3.24版本
我们使用strtus2框架不是直接将它的lib包下的所有的jar文件copy到项目中,而是使用其中的一部分。
我们可以参考它的示例代码:
1.导入13个jar包
2.需要在web.xml文件中配置StrutsPrepareAndExecuteFilter 3.创建一个struts.xml文件,它的位置是可以放置在src下。
黑马程序员郑州中心 编著
6.3.1 代码实现 6.3.1.1 jsp页面
6.3.1.2 Action
6.3.1.3 struts.xml文件配置
6.3.2 流程分析
黑马程序员郑州中心 编著
6.4 使用struts2完成简单登录操作
1.login.jsp页面不变动
2.创建一个LoginAction来完成逻辑操作 3.在struts.xml文件中完成配置操作
问题1:在LoginAction中如何得到username与password 可以直接在Action类中提供成员属性,并为其提供get/set方法。就可以得到请求参数
问题2:如果实现路径跳转?
1.我们可以给action中的方法添加一个String返回值
2.在struts.xml配置文件中,在其对应的action配置上通过来确定跳转的路径。
黑马程序员郑州中心 编著
第7章 Struts2框架执行流程
7.1 Struts2源码导入
对于struts2框架它的源代码我们主要使用三部分 1.struts2核心部分源代码
org.apache.struts2xx
srccoresrcmainjava
2.struts2的xwork核心部分源代码
srcxwork-coresrcmainjavacomopensymphonyxwork2 3.struts2的插件的源代码
srcplugins 7.2 关于struts.xml配置文件中提示问题
第一步
在eclipse的window下首选面中查找xml catalog 第二步
Location:配置本地的dtd文件路径 key type:选择URI
黑马程序员郑州中心 编著
Key: http://struts.apache.org/dtds/struts-2.3.dtd
注意版本要对应,如果你可以上网,那么会自动缓存dtd,具有提示功能。
7.3 执行流程介绍
1.当通过浏览器发送一个请求
2.会被StrutsPrepareAndExecuteFilter拦截
3.会调用strtus2框架默认的拦截器(interceptor)完成部分功能 4.在执行Action中操作
5.根据Action中方法的执行结果来选择来跳转页面Resutl视图
一般管StrutsPrepareAndExecuteFilter 叫做前端控制器(核心控制器),只有配置了这个filter我们的strtus2框架才能使用。
黑马程序员郑州中心 编著
Strtus2的默认拦截器(interceptor)它们是在struts-default.xml文件中配置 注意:这上xml文件是在strtus-core.jar包中。默认的拦截器是在defaultStack中定义的。
第8章 Struts2配置详解
8.1 Struts2配置文件加载顺序
第一个加载的是default.properties文件
位置:strtus2-core.jar包
org.apache.struts2包下 作用:主要是声明了struts2框架的常量
第二个加载的是一批配置文件
Strtus-default.xml 位置:struts2-corl.jar
作用:声明了interceptor result bean Strtus-plugin.xml 位置:在strtus2的插件包中 作用:主要用于插件的配置声明 Strtus.xml
黑马程序员郑州中心 编著
位置:在我们自己的工程中
作用:用于我们自己工程使用strtus2框架的配置 第三个加载的是自定义的strtus.properties 位置:都是在自己工程的src下 作用:定制常量 第四自定义配置提供
第五加载的是web.xml配置文件
主要是加载strtus2框架在web.xml文件中的相关配置.第六 bean相关配置
重点掌握: 1.Default.properties 2.Struts-default.xml 3.Struts-plugin.xml 4.Strtus.xml 5.web.xml
8.2 struts.xml文件配置介绍
8.2.1 package配置
1.name属性
作用:定义一个包的名称,它必须唯一。
黑马程序员郑州中心 编著
2.namespace属性 作用:主要是与action标签的name属性联合使用来确定一个action 的访问路径
3.extends属性 作用:指定继承自哪个包。一般值是strtus-default strtus-default包是在strtus-default.xml文件中声明的。
4.abstruct属性 它代表当前包是一个抽象的,主要是用于被继承
8.2.2 action配置
1.name属性 作用:主要是与package的namespace联合使用来确定一个action的访问路 径
2.class属性
作用:用于指示当前的action类
3.method属性
作用:用于指示当前的action类中的哪个方法执行
8.2.3 result配置
它主要是用于指示结果视图
1.name属性 作用是与action类的method方法的返回值进行匹配,来确定跳转路径 2.type属性 作用是用于指定跳转方式
8.2.4 扩展
关于action配置中的class与method的默认值以及result中的name与type 默认值问题
原因:strtus-default.xml文件中配置
黑马程序员郑州中心 编著
它的作用就是当一个请求来时,如果查找不到指定的class及对应的method就会执行 ActionSupport类中的execute方法。
在这个类的execute方法中默认返回的是”success”
也就是说,result的name属性默认值是success,默认的跳转方式是请求转发 dispatcher
8.3 常量配置
default.properties文件中定义了struts2框架常用常量.问题:我们怎样可以定义常量
1.可以在src下创建一个strtus.properties配置文件 2.可以在web.xml文件中配置
3.可以直接在strtus.xml文件中定义常量(推荐)
注意:后加载的配置文件中的常量会将先加载的常量覆盖
第9章 Struts2的Action详解
Struts2中的action,主要是完成业务逻辑操作。Action替代在servlet中完成的作用。
黑马程序员郑州中心 编著
Action的学习主要有两点
1.如何创建一个struts2的action 2.如果访问一个struts2的action
1. Action类创建方式(三种)1.创建一个pojo类
Pojo(plani Ordinary java object)简单的java对象 Pojo类就是没有实现任何接口没有继承任何类 优点:无耦合
缺点:所有的功能都要自己完成
2.创建一个类实现一个Action接口
com.opensymphony.xwork2.Action
在Action接口中定义了五个常量,一个execute方法 五个常量:它们是默认的五个结果视图: ERROR : 错误视图
INPUT: 它是struts2框架中interceptor中发现问题后会访问的一个视图 LOGIN:它是一个登录视图,可以在权限操作中使用
黑马程序员郑州中心 编著
NONE:它代表的是null,什么都不做(也不会做跳转操作)SUCCESS:这是一个成功视图 优点:耦合度低
缺点:还是需要自己来完成功能
3.创建一个类继承ActionSupport类
com.opensymphony.xwork2.ActionSupport ActionSupport类也实现了Action接口。我们在开发中一般会使用这种方案: 优点:具有丰富的功能,例如
表单校验 错误信息设置
国际化 缺点:耦合度高
9.1 action的访问方式
1.直接通过标签来配置,通过method来指定访问的方法,如果method没有,默认访问的是execute方法。
2.简化的action访问方式,可以使用*通配符来访问。
这种方式的缺点:不建议使用过多的*号,它带来程序阅读障碍,不便于理解 使用*来简化操作方案,它对名称规范必须进行一个统一。
黑马程序员郑州中心 编著
9.2 扩展--动态方法调用
这是strtus2提供的动态方法调用。
注意:对于strtus2的动态方法调用,要想使用我们必须配置一个常量来开启动态方法调用
这代表动态方法调用没有开启
黑马程序员郑州中心 编著
个人不建议使用动态方法调用
第10章 Struts2框架封装数据
主要解决的问题:是在action中如果获取请求参数
主要有两种方式: 1.属性驱动
a.直接在action类中提供与请求参数匹配属性,提供get/set方法
b.在action类中创始一个javaBean,对其提供get/set,在请求时页面上要进行修改,例如 user.username user.password ,要使用ognl表达式
以上两种方式的优缺点: 第一种比较简单,在实际操作我们需要将action的属性在赋值给模型(javaBean)去操作 第二种:不需要在直接将值给javaBean过程,因为直接将数据封装到了中。它要求在页面上必须使用ognl表达式,就存在页面不通用问题。javaBean
2.模型驱动
步骤: 1.让Action类要实现一个指定接口ModelDriven 2.实例化模型对象(就是要new出来javaBean)3.重写getModel方法将实例化的模型返回。
黑马程序员郑州中心 编著
对于模型驱动它与属性驱动对比,在实际开发中使用比较多,模型驱动缺点,它只能对
一个模型数据进行封装。
第11章 总结
今天主要内容是围绕着简单的登录案例来讲解: 1.关于strtus2框架的环境搭建 2.关于strtus2框架配置 3.关于strtus2框架请求参数封装 4.关于strtus2框架的路径跳转
关于action访问的配置
黑马程序员郑州中心 编著
namespace=””
extends=””> class=””
method=””>
路径
关于路径跳转问题: 是通过来配置跳转的路径.它的name属性是与action中的方法的返回值进行对比的。它的type属性可以取哪些值?
默认值是dispatcher 它代表的是请求转发。针对于jsp页面 redirect 它代表的是重定向
针对于jsp页面
chain 它类似于请示转发,只不过它是针对于action跳转.redirectAction 它类似于重定向
针对于action 关于路径跳转的配置
可以直接在
下创建全局的result
黑马程序员郑州中心 编著
黑马程序员郑州中心 编著
【黑马程序员】Java基础 : Java语句笔记
摘要: Java基础—java语句这些是黑马程序员java基础入门的一个很重要的内容。今天主要给大家简单讲解一下Java基础—java语句,以后会慢慢讲解黑马程序员的课程内容!
关键语句介绍
一、while 语句 一般形式:
whi l e(条件表达式){ 语句体 ……… } 执行过程:
条件表达式为真,执行语句体。否则,退出!
二、do while 语句 一般形式: do { 语句体 …….} while(条件表达式);执行过程:
先执行一次语句体,判断 条件表达式是否为真,为真再执行do语句中的语句体。为假,退出。
需要注意:与whi l e语句区别
黑马程序员合肥中心 编著
1.while(条件表达式)后面有分号;2.不管条件表达式是否为真,语句体均会执行一次。
三、for 语句 一般形式:
for(子句 1;子句 2;子句 3){ 语句体 …… } 执行过程:
四、break、cont inue 语句 break 退出所在循环 : int stopHere = 5;for(int i=1;i<8;i++){ if(i == stopHere){ break;} System.out.println(“i = ” + i);
黑马程序员合肥中心 编著
} //打印结果:5,6,7,8均没有打印出来。
需要注意的一个问题: int stopHere = 5;for(int i = 1;i < 8;i + +){ if(i = = stopHere){ / /语句体 } break;System.out.println(“i = ” + i);} 这个时候编译器会报错:无效的 System.out 输出语句。冷静分析一下:
break 语句会结束循环,所以不会再去执行 System.out 输出语句。编译会认为你在多此一举,sorry 报个错!
continue 退出本次循环,不会退出整个循环: int skipHere = 5;for(int i = 1;i < 8;i + +){ if(i = = skipHere){ continue;}
黑马程序员合肥中心 编著
System.out.println(“i = ” + i);} / /打印结果:除了5没有打印出来。
i = 1 i = 2
五、switch 语句 一般形式: switch(常量){ case 表达式1:语句体1;break;case 表达式2:语句体2;break;.....default : 语句体n;break;}
执行过程: 执行过程:
case 根据自己的表达式看是否匹配常量,如果匹配就执行语句体,否则执行 default 语句。
case 执行类似于并行操作,不是顺序操作。所以各个表达式的值不可以相同。
黑马程序员合肥中心 编著
哪个 case 匹配常量就会执行自己的语句体,不会再去寻找其他 case 语句。注意:
<1> case 穿透:省去break关键字
[AppleScript] 纯文本查看 复制代码 ?
01 /**
02 * @author 传智播客 03 */
04 int i = 10;05 switch(i){ 06 case 10:
07 System.out.println(“ A”);08 //break;09 case 5: System.out.println(“ B”);11 //break;12 case 7: System.out.println(“ C”);14 //break;15 default : System.out.println(“ error”);17 break;18 }//打印结果:A B C error
<2> 在 Java 编程中 switch 括号中的常量的数据类型只可以为 int 类型或者是 byte、char、short(因为 byte、char、short 可以自动提升为 int),常量类型不可以是 long、float 和 double 等数据类型。<3> 多个 case 可以合并 , 相当于 “ 或 ”,例如下面 i 等于 10、5、7 都可以执行打印语句。
[AppleScript] 纯文本查看 复制代码 ?
01 /**
02 * @author 传智播客 03 */
04 int i = 5;05 switch(i){ 06 case 10: 07 case 5: 08 case 7:
09 System.out.println(“ C”);10 break;11 default : System.out.println(“ error”);13 break;
黑马程序员合肥中心 编著 }//打印结果:C <4> default 语句可以省,但是不推荐,他后面的 break 可省 <5> case 或者 default 子句中可以写多条语句 case 7: System.out.println(“ C”);if(i == 5){ System.out.println(“ i = ” +i);} break;<6> case 或者 default 子句中还可以嵌套 switch 或者其他语句
六、return 语句
终止方法的运行并指定要返回的数据。两种形式:
<1> return 表达式;
<2> return ;没有任何数据直接返回,结束函数(方法)的执行。
七、if 语句
一般形式:
1.if(条件表达式){ 语句体} 2.if(条件表达式){ 语句体} else{语句体 } 3. if(条件表达式1){ 语句体} else if(条件表达式2){语句体 } else {语句体 }
特别注意:形式3,else与其最近的上个if 配对。例子:
[AppleScript] 纯文本查看 复制代码 ?
黑马程序员合肥中心 编著
01 /**
02 * @author 传智播客 03 */
04 public class TestIF {
05 public static void main(String[] args){ 06 int i = 30;07 if(i < 20){
08 System.out.println(“<20”);09 } else if(i < 50){ System.out.println(“<50”);11 } else if(i < 80){ System.out.println(“<80”);13 } else System.out.println(“>=80”);15 System.out.println(“黑马程序员!”);16 }
如果大家想学习java基础的知识,欢迎大家可以去传智播客官网http://www.xiexiebang.com/去了解java基础知识!
黑马程序员合肥中心 编著
01、什么是3G 02、android系统简介 03、android背景介绍 04、android的framewor简介 05、两种虚拟机的比较 06、sdk的下载以及简介 07、创建android模拟器 08、ddms简介
09、platform-tools的简介及常见adb指令
10、android项目的目录结构
11、android下apk安装的过程
12、常见的adb指令介绍
13、创建模拟器遇到的常见错误
14、电话拨号器
15、点击事件的四种写法
16、短信发送器
17、相对布局&单位介绍
18、现形布局&布局的组合
19、表格布局&绝对布局 20、帧布局
21、测试相关概念
22、android下junit测试框架配置
23、logcat简介
24、保存文件到手机内存
25、android下文件访问的权限
26、保存文件到SD卡中
27、分析setting源代码获取SD卡大小
28、_sharePreference入门
29、xml文件的序列化 30、采用pull解析xml文件
31、采用断电调试的方法观察pull解析的的流程
32、android下创建一个sqllite数据库
33、sql语句实现数据库的增删改查
34、系统api实现数据库的增删改查&Sqlite3工具的使用
35、数据库的事物
36、listView入门
37、采用layoutInflater打气筒创建一个view对象
38、采用数据适配器ArryAdapter
39、常用数据适配器simpleAdapter 40、数据适配器总结
41、内容提供者简介
42、内容提供者的实现
43、短信的备份
44、插入一条记录到系统短信应用
45、内容观察者
46、获取系统的联系人信息
47、保存联系人到系统通讯录
48、读取联系人的一个小细节
49、网络图片查看器
50、anr产生的原理&如何避免
51、android消息机制入门
52、网络html查看器
53、字符乱码问题的处理
54、采用get方式提交数据到服务器
55、采用post方式提交数据到服务器
56、提交数据到服务器中文乱码问题的处理
57、采用httpclient提交数据到服务器
58、异步http框架简介&实现原理
59、异步http框架提交数据到服务器 60、上传文件到服务器
61、smartimageview&常见开源代码 62、多线程下载的原理 63、多线程断点下载的原理
64、多线程java代码移植到android 65、多线程下载文本页面的更新 66、显示意图激活另一个activity 67、隐式意图激活另一个activity 68、隐式意图的配置
69、隐式意图和显示意图的使用场景 70、在不同activity之间数据传递 71、activity的声明周期 72、activity的启动模式
73、activity横竖屏切换的声明周期 74、开启新的activity获取他的返回值 75、请求码和结果码的作用 76、利用广播实现ip拨号 77、短信窃听器
78、自定义广播时间&发送自定义广播&广播接受者优先级 79、采用服务执行长期后台操作 80、采用服务窃听电话&服务的声明周期 81、android进程优先级&为什么使用服务 82、绑定方式开启服务&调用服务的方法 83、服务的声明周期(混合开启 84、采用aidl绑定远程服务
85、代码注册广播接受者&利用广播调用服务的办法 86、加载大图片到内存 87、获取图片exif信息 88、从gallery获取图片 89、图片画画板 90、扒开美女衣服 91、图片的缩放 92、图片的旋转
93、图片的平移&镜面&倒影效果 94、图片的合成 95、图片的颜色处理 96、多媒体播放api简介 97、人脸识别
98、mediaplayer的生命周期 99、soundpoo简介
100、sufaceview的生命周期 101、播放在线视频
102、视频播放器进度的处理 103、调用系统照相机拍照和录像 104、采用camera拍照 105、常见对话框 106、notification入门 107、菜单
108、android下的样式 109、android下的主题
110、代码编写ui 111、html创建ui 112、帧动画
113、代码创建创建的tween动画 114、xml文件定义动画 115、传感器简介 116、117、杀死进程 118、apk的安装 119、应用程序的反编译 120、动态创建fragment 121、用fragment创建一个选项卡 122、fragment的向下兼容性 123、fragment的生命周期 124、fragment之间的通讯 125、应用程序国际化
04、android的framewor简介
Wap:wait and play Wireless Makeup Language(WML)精简的html语言 Applications:android自带的基本上层应用 Aplication framework:应用程序框架 Librarics: Linux lernel:
05、两种虚拟机的比较
编译后文件格式:
jvm:.java->.class->.jar dalvik vm:.java->.dex->.odex 基于的架构:
jvm:基于栈的架构
dalvik vm:基于寄存器的架构
Cpu直接访问寄存器因此dalvik虚拟机的效率比jvm高
06、sdk的下载以及简介
->获取sdk工具包(sdk:standard develope kits)->ADT(android develop tools,实际上是eclipse的插件)SDK具体内容
Android 4.2.2(API16)
->SDK Plateform:开发时使用到的jar包->Samples for sdk:
->ARM EABI V7a System Image:模拟器运行时的镜像->Intel n86 Aton System:模拟器运行时的镜像->MIPS System Image:模拟器运行时的镜像->google APIs:google提供的jar包,可以直接使用google提供的一些API->source for android SDK:SDK全部的源代码 Extrals:
->tools:开发的工具
->support library:实现高版本的android向下的兼容->google Admed Ads SDK:gongle提供的广告插件->Analyties App Irackiong SDK:应用的用户分析->cloud message:云消息
->gongle play service:收费服务
->google USB Driver:真实的设备驱动
开发时:基于4.0,兼容2.2、2.3.3
07、创建android模拟器
avd:android virture developer VGA:480*640(电视的标准分辨率)QVGA:240*320(四分之一)HVGA:320*480(一半)WVGA:480*800(width)FWVGA:480*854(更宽)
08、ddms简介
ddms:模拟器不支持中文,因此发送中文会显示不出来
09、platform-tools的简介及常见adb指令
Android调试桥:内部实现就是socket让两个系统之间实现数据交互
->reset adb:模拟器找不到时候可以重启->adb device:列出所有的连接的设备->adb kill-server:杀死adb调试桥->adb start-server 启动adb调试桥 dx.bat:将.class文件打包
10、android项目的目录结构
一:SDK的目录结构
->Samples->Api demo:根据API demo(模拟器上面可以看见)的效果可以在sample中看见
相应的代码
->Source:jar包所有的sdk源代码都在这个文件夹里->SystemImage:系统镜像
->temp:下载更新临时存储的文件夹,一般是空的->tools:emulater.ext 不同版本的模拟器
二:New Android Application->theme:留给以后作为扩展,现在并没有太大的作用->target SDK:一般选择高版本,因为高版本对下兼容
->mark project as a library:一般不选择,意思是将这个项目提供一个
jar包供别人使用 三:文件夹目录
.setting:设置目录
assets:资产目录,存放一些文件,这些文件会被原封不动打包到应用程序的 apk中
bin:
gen:自动生成的目录
->builderConfig.java:生成的配置信息->R.java: Android 4.1.2->android.jar开发环境,jar包
可以在properties中修改,jar包就是SDK
011、Android下apk的安装过程
一、Android安装过程分析:
->setContentView:甚至view的对象,把里面的xml文件加载到
->在project中选择build automaticly会自动把文件生成字节码文件,.class $代表的class文件生成的是内部类->dex.bat文件会把.class文件生成.dex文件
->apk压缩文件解压内部内容
->META-INF: 应用程序的签名
eclipse的调试签名文件
->res:资源文件
->classes.dex:class文件
->resources.arsc:资源ID映射
->android软件安装的过程:
->拷贝xxx.apk带/data/app/xxx-1.apk->在/data/data目录下创建一个文件夹,文件夹名称当前应用程序的报名
012、常见adb指令
前提:
->设备连接上电脑而且驱动安装正常,如果安装不正常的话,会有黄色的问号显示;
->设备上打开USB调试;
指令:
->adb device(如果启动发现这个程序没有安装会自动安装)->adb kill-server->adb start-server->adb uninstall <包名>->adb-s emulator-5554 install c:usersadministratorhello.apk 如果有多个设备的话,如果不指定安装的是哪个设备程序会报错->adb push haha.prop /sdcard/haha.txt 将文件移到
(360管家,豌豆荚之类的软件他们也是用的adb指令,倘若电脑上装这些软件的话,会因为两个adb指令抢端口号而挂掉)(adb版本之间兼容不是很好,经常报错可以考虑下版本的问题)->adb shell:远程连接到了android的linux终端
ls:显示文件夹
ps:显示正在运行的程序 ping:网络连通性
013、创建模拟器遇到的常见错误
->路径最好不要有中文:
->应用安装不上,或者安装模拟器的时候开启一个新的模拟器:
可能是模拟器的资源被占用,模拟器在运行的时候其实占用着硬盘上面的一个文件,这个文件位于工作空间.android/avd/iphone.avd 里面会有镜像文件,当一个模拟器开启起来了,就给你创建一个文件夹.knock的文件夹,代表着这个模拟器被锁定了,如果把模拟器关掉,就没有程序占据这几个镜像资源了,那么这几个程序就会被自动删除。通常情况下不会出问题,开启时候创建文件,关闭时关闭文件,但是当电脑出现不正常状态时:比如蓝屏,停电关机时候这些资源还没来得及删除,模拟器就关闭了,因此开启时这些资源仍在,程序默认模拟器被占用,因此会重新开启一个模拟器。
->模拟器没有信号:
模拟器用socket桥接在电脑上
终结解决方案是给电脑连上网,分配一个IP->常见命令操作:
14、电话拨号器
->新建文件
->界面设置:文本框、点击按钮
-> :一旦获得焦点,会立刻弹出,输入文本的软键盘->ctrl+x删除->ctrl+1提示
->设置点击事件:找到空间,然后设置点击事件,再点击事件里面获得了另外一
个空间的数据,激活一个intent->获得权限:清单文件中添加uses permision
15、点击事件的四种写法
->电话拨号器的优化:
每次拨打电话都会执行的操作是:查找控件,然后找到控件的文本,拨打电
话。其实每次拨打电话文本控件已经创建好了没有必要每次查找按钮之后再 查询控件。
package cn.wqrt.mobile;
import android.app.Activity;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.text.TextUtils;import android.view.Menu;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.Toast;
public class MainActivity extends Activity {
private EditText et_number;@Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button button =(Button)findViewById(R.id.bt_dial);et_number =(EditText)findViewById(R.id.et_number);button.setOnClickListener(new MyListener());}
private class MyListener implementsandroid.view.View.OnClickListener{
@Override
public void onClick(View arg0){
String number = et_number.getText().toString().trim();//去除回车和空格
if(TextUtils.isEmpty(number)){
Toast.makeText(MainActivity.this, “号码不能为空”, Toast.LENGTH_SHORT).show();
return;
}
Intent intent = new Intent();
intent.setAction(intent.ACTION_CALL);
intent.setData(Uri.parse(“tel:”+number));
startActivity(intent);
}
}
@Override public boolean onCreateOptionsMenu(Menu menu){ // Inflate the menu;this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;} }
->
1、点击事件的四种写法:
->给按钮注册点击事件:创建一个内部类定义点击事件。具体代码见上
button.setOnClickListener(new MyListener());
->
2、采用匿名内部类创建点击事件:
button.setOnClickListener(new OnClickListener()){
package cn.wqrt.mobile;
import android.app.Activity;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.text.TextUtils;import android.view.Menu;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.Toast;
public class MainActivity extends Activity {
private EditText et_number;@Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button button =(Button)findViewById(R.id.bt_dial);et_number =(EditText)findViewById(R.id.et_number);button.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View arg0){
// TODO 自动生成的方法存根
callPhone();
}
});}
@Override public boolean onCreateOptionsMenu(Menu menu){ // Inflate the menu;this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}
private void callPhone(){
String number = et_number.getText().toString().trim();//去除回车和空格
if(TextUtils.isEmpty(number)){
Toast.makeText(MainActivity.this, “号码不能为空”, Toast.LENGTH_SHORT).show();
return;
}
Intent intent = new Intent();
intent.setAction(intent.ACTION_CALL);
intent.setData(Uri.parse(“tel:”+number));
startActivity(intent);} } }
->
3、如果有很多的按钮点击事件,建议用这种方式:让Activity实现点击 事件的接口,每个按钮点击事件都设置成this,让该类实现 OnClickListener然后进行判断。package cn.wqrt.mobile;
import android.app.Activity;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.text.TextUtils;import android.view.Menu;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener {
private EditText et_number;@Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button button =(Button)findViewById(R.id.bt_dial);et_number =(EditText)findViewById(R.id.et_number);button.setOnClickListener(this);}
@Override public boolean onCreateOptionsMenu(Menu menu){ // Inflate the menu;this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}
private void callPhone(){
String number = et_number.getText().toString().trim();//去除回车和空格
if(TextUtils.isEmpty(number)){
Toast.makeText(MainActivity.this, “号码不能为空”, Toast.LENGTH_SHORT).show();
return;
}
Intent intent = new Intent();
intent.setAction(intent.ACTION_CALL);
intent.setData(Uri.parse(“tel:”+number));
startActivity(intent);}
@Override public void onClick(View v){
// TODO 自动生成的方法存根
switch(v.getId()){
case R.id.bt_dial:
callPhone();
break;
} } }->
4、在布局文件中绑定一个点击的方法,如果点击按钮就会调用这个方法,通
过反射技术试图调用这个方法
布局文件中设置: package cn.wqrt.mobile;
import android.app.Activity;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.text.TextUtils;import android.view.Menu;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.Toast;
public class MainActivity extends Activity {
private EditText et_number;@Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button button =(Button)findViewById(R.id.bt_dial);et_number =(EditText)findViewById(R.id.et_number);
}
@Override public boolean onCreateOptionsMenu(Menu menu){ // Inflate the menu;this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}
public void dialButtonClick(View v){ callPhone();}
private void callPhone(){
String number = et_number.getText().toString().trim();//去除回车和空格
if(TextUtils.isEmpty(number)){
Toast.makeText(MainActivity.this, “号码不能为空”, Toast.LENGTH_SHORT).show();
return;
}
Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse(“tel:”+number));
startActivity(intent);} }
16、短信发送器
->界面的设计:两个large Text,一个Button
android:textColor 设置字体颜色
android:singleLine=“true” 设置是否是单行
android:lines=“5” 设置行数
windows下面的颜色是GBR,而android下需要输入的格式确实
RGB,所以需要转换
adb默认设置time out为5秒->内容设计:按钮-文本->判断->发送
导包的时候千万别导到gsm包,否则会显示过时;
发送没有历史记录 package com.example.sms;
import java.util.ArrayList;
import android.app.Activity;import android.os.Bundle;import android.telephony.SmsManager;import android.text.TextUtils;import android.view.Menu;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener {
private EditText et_number;private EditText et_content;
@Override protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button =(Button)findViewById(R.id.bt_send);
et_number =(EditText)findViewById(R.id.et_number);
et_content =(EditText)findViewById(R.id.et_content);
button.setOnClickListener(this);}
@Override public boolean onCreateOptionsMenu(Menu menu){
// Inflate the menu;this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);
return true;}
@Override public void onClick(View v){
// TODO 自动生成的方法存根
switch(v.getId()){
case R.id.bt_send:
String number = et_number.getText().toString().trim();
String content = et_content.getText().toString().trim();
if(TextUtils.isEmpty(number)||TextUtils.isEmpty(content)){
Toast.makeText(this, “号码或者内容不能为空”,Toast.LENGTH_SHORT).show();
return;
}else{
SmsManager smsManager = SmsManager.getDefault();
ArrayList contents = smsManager.divideMessage(content);
for(String str:contents){
smsManager.sendTextMessage(number, null, str, null, null);
}
}
} } }
17、相对布局&单位介绍
->布局说明:
->同级控件:
android:layout_toRightOf=“" android:layout_toLeftOf=”“ android:layout_below=”' android:layout_above=“" android:layout_maginBottom=”“
->相对父控件:
android:ayout_centerInParent=”“ android: layout_centerHorizontal=”“ android:layout_centerVertical=”“ android:layout_alignParentBottom=”“ android:layout_alignParentRight=”“->对齐方式:
->文本颜色:#00000000~#ff000000(argb)文字的透明度->单位介绍:
dp也就是dip:device independent pixels(设备独立像素),是一种与密度无关的像素单位,在每英寸160点的屏幕上,1dp = 1px。不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA、HVGA和QVGA 推荐使用这个,不依赖像素
1.2.android:layout_height=”wrap_content“
3.android:text=”@string/clickme“
4.android:layout_marginTop=”20dp“ />
scaled pixels(刻度像素).主要用于定义字体的大小,而从来不再layout上使用
o
1.2.android:layout_height=”wrap_content“
3.android:textSize=”20sp“ />
px:pixels(像素).不同设备显示效果相同,一般我们HVGA代表320x480像素,这个用的比较多 总结:dp也就是dip。这个和sp基本类似。如果设置表示长度、高度等属性时可以使用dp或sp。但如果设置字体,需要使用sp。dp是与密度无关,sp除了与密度无关外,还与scale无关。如果屏幕密度为160,这时dp和sp和px是一样的。1dp=1sp=1px,但如果使用px作单位,如果屏幕大小不变(假设还是3.2寸),而屏幕密度变成了320。那么原来TextView的宽度设成160px,在密度为320的3.2寸屏幕里看要比在密度为160的3.2寸屏幕上看短了一半。但如果设置成160dp或160sp的话。系统会自动将width属性值设置成320px的。也就是160 * 320 / 160。其中320 / 160可称为密度比例因子。也就是说,如果使用dp和sp,系统会根据屏幕密度的变化自动进行转换.附:px 和 dp 互转换
1.package com.hujl.util;import android.content.Context;
public class DensityUtil {
/**
* 根据手机的分辨率从 dp 的单位转成为 px(像素)
*/
public static int dip2px(Context context, float dpValue){
final float scale = context.getResources().getDisplayMetrics().density;
return(int)(dpValue * scale + 0.5f);
}
/**
* 根据手机的分辨率从 px(像素)的单位转成为 dp
*/
public static int px2dip(Context context, float pxValue){
final float scale = context.getResources().getDisplayMetrics().density;
return(int)(pxValue / scale + 0.5f);
} }
18、线性布局&布局的组合
->线性布局:
->线:就是view对象
android:layout_height=”1px“
android:background=”#ff0000“ > />
通常采用相对布局和绝对布局联合使用的方式。
19、表格布局&绝对布局
->表格布局:渲染权重
->绝对布局:对控件位置任意摆放,需要计算不同屏幕中的位置,因为android
软件的屏幕大小实在太多,所以并不方便,不推荐使用。
20、帧布局
>帧布局:
->类似于网页布局中的div
android:visibility:”“ //显示是否可见,播放器最喜欢使用帧布局,暂停播放的时候,会在上面显示一个按钮
21、测试相关概念
->根据测试测试是否知道程序的源代码:
->黑盒测试:不知道源代码,只关心程序执行的过程和程序的结果,一个资
深的黑盒程序人员工资很高,因为他们和正常用户的使用思维
不一样
->白盒测试:根据源代码写测试方法或者测试用例->根据测试的粒子度:
->方法测试:function test->单元测试:unit test->集成测试:intergration test->根据测试的次数:
->冒烟测试:smoke test 反复不停的执行,反复不停的使用(android猴子
来测试)
->adb shell
->monkey
->monkey 5000(点击五千次)
->压力测试:pressure test同时抗住多人的请求->
22、android下junit测试框架配置
23、logcat简介
->日志信息级别:
Verbose:提醒 黑色
Debug: 调试 蓝色
Info: 信息 绿色
Warn: 警告 橙色
Error: 错误 红色
24、保存文件到手机内存
->数据存储与访问
->文件
->SharePreferences(参数)
->SQLite数据库
->内容提供者(Content Provide)
->网络
->LinearLayout一定要设置水平还是垂直->文件保存:
->javase中通过创建文件对象,但是在androi中这种存放方式会失败,因
为会默认为存储在当前目录文件下
->android中创建一个包:com.itheima.login.service
创建一个类:LoginService.java
异常的处理:如果是返回值是boolean,那么抛出处理都可以,但是如果返回值是void,那么只能抛出了
->context:上下文就是一个类,这个类提供了很多方便的API,可以得到应用程
序的环境
环境包名 安装路径 文件的路径 资源的路径 资产的路径
放到缓存文件夹里面:getCacheDir();->getAssest();->getResource();->getFilesDir();/data/data/包名
->getCacheDir();/data/data/包名/cache
->MainActivity.java package com.example.login;
import java.util.Map;
import android.app.Activity;import android.os.Bundle;import android.text.TextUtils;import android.view.Menu;import android.view.View;import android.widget.CheckBox;import android.widget.EditText;import android.widget.Toast;
import com.example.login.service.LoginService;
public class MainActivity extends Activity {
private EditText et_number;private EditText et_passwd;private CheckBox cb_remPass;
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);//首先要把页面加载进来然后才有控件的获取
et_number =(EditText)findViewById(R.id.et_number);
et_passwd =(EditText)findViewById(R.id.et_passwd);
cb_remPass =(CheckBox)findViewById(R.id.cb_remPass);
Map map = LoginService.getSavaUserInfo(this);
if(map!= null){
et_number.setText((CharSequence)map.get(”username“));
et_passwd.setText((CharSequence)map.get(”passwd“));
} }
@Override public boolean onCreateOptionsMenu(Menu menu){
// Inflate the menu;this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);
return true;} public void login(View v){
String number = et_number.getText().toString().trim();
String passwd = et_passwd.getText().toString().trim();
if(TextUtils.isEmpty(number)||TextUtils.isEmpty(passwd)){
Toast.makeText(this, ”登录名或者密码不能为空“, Toast.LENGTH_SHORT).show();
return;
}else{
if(cb_remPass.isChecked()){
//如果选择了保存用户密码,那么就保存用户密码
boolean results = LoginService.saveuserInfo(this,number, passwd);
if(results){
Toast.makeText(this, ”保存用户信息成功“, Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, ”保存用户信息失败“, Toast.LENGTH_SHORT).show();
}
}
//登陆发送消息到服务器,服务器验证是否正确
if(”zhangsan“.equals(number)&&”123456“.equals(passwd)){
Toast.makeText(this, ”登陆成功“, Toast.LENGTH_LONG).show();
}else{
Toast.makeText(this, ”登录失败,用户名或者密码不正确“, Toast.LENGTH_LONG).show();
}
} } }
->LoginService.java package com.example.login.service;
import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.util.HashMap;import java.util.Map;
import android.content.Context;/* * 保存用户名密码的的业务方法 */ public class LoginService { public static boolean saveuserInfo(Context context,String userName,String passWord){//没有使用任何类的方法,推荐使用静态方法
//File file = new File(”/data/data/com.example.login/info.txt“);
File file = new File(context.getFilesDir(),”info.txt“);
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write((userName+”##“+passWord).getBytes());
fos.close();
return true;
} catch(FileNotFoundException e){
// TODO 自动生成的 catch 块
e.printStackTrace();
return false;
} catch(IOException e){
// TODO 自动生成的 catch 块
e.printStackTrace();
return false;
}
} /* * 获取保存到的数据
*/ public static Map getSavaUserInfo(Context context){
File file = new File(context.getFilesDir(),”info.txt“);
Map map = new HashMap();;
try {
FileInputStream fis = new FileInputStream(file);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fis));
String str = bufferedReader.readLine();
String[] infos = str.split(”##“);
map.put(”username“, infos[0]);
map.put(”passwd“, infos[1]);
} catch(FileNotFoundException e){
// TODO 自动生成的 catch 块
e.printStackTrace();
return null;
} catch(IOException e){
// TODO 自动生成的 catch 块
e.printStackTrace();
return null;
}
return map;} }
->activity_main.xml
android:id=”@+id/bt_login“
android:onClick=”login“
android:layout_width=”100dp“
android:layout_height=”wrap_content“
android:layout_alignParentRight=”true“
android:text=”@string/bt_login“
/>
android:id=”@+id/cb_remPass“
android:layout_width=”wrap_content“
android:layout_height=”wrap_content“
android:layout_alignParentLeft=”true“
android:layout_alignParentTop=”true“
android:layout_alignBottom=”@id/bt_login“
android:text=”@string/remPass“
android:checked=”true“ />
25、android下文件访问的权限
->private、readable、writeable、public
26、保存文件到SD卡中
->存储空间:
->手机的内部存储空间:小硬盘 /data/data->外部存储空间:SD卡 路径/mnt/sdcard 可以简写成/sdcard/
需要权限WRITE_EXTER_STORAGE
操作SD卡必须要权限
->保存数据到SD卡只需要把路径改为SD卡,读不需要权限,否则需要权限
在4.0以前的版本读SD卡不需要权限,但是在4.0以
后读写SD卡可以设置SD卡保护,读就需要权限 READ_EXTER_STORAGE->判断是否存在SD卡:Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
->为了保证程序的兼容性,有些SD卡可能路径会改变,因此系统提供了获取SD 卡的路径的方法
Environment.getExternalStorageDirectory()
27、分析setting源代码获取SD卡大小
->source的源代码是SDK的源代码,是jar里面的源代码->导入通用的文件项目eclipse要求必须要有setting文件->ctrl+h搜索文件夹
package com.example.sdsize;
import java.io.File;
import android.app.Activity;import android.os.Bundle;import android.os.Environment;import android.os.StatFs;import android.text.format.Formatter;import android.view.Menu;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;import android.widget.Toast;
public class MainActivity extends Activity {
private TextView tv_SDsize;protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button =(Button)findViewById(R.id.bt_find);tv_SDsize =(TextView)findViewById(R.id.tv_SDSize);
button.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View arg0){
// TODO 自动生成的方法存根
StringBuilder memorySizeInfo = new StringBuilder();
if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())){
memorySizeInfo.append(getExternalSize());
}else{
Toast.makeText(MainActivity.this,”无内存卡“, Toast.LENGTH_SHORT).show();
}
memorySizeInfo.append(getRomSpaceInfo());
tv_SDsize.setText(memorySizeInfo.toString());
}
});} /* * 获取SD卡的存储信息 */ public String getExternalSize(){
File path = Environment.getExternalStorageDirectory();
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long totalBlocks = stat.getBlockCount();
long availableBlocks = stat.getAvailableBlocks();
long totalSize = blockSize*totalBlocks;
long availSize = blockSize*availableBlocks;
String totalStr = Formatter.formatFileSize(this, totalSize);
String availStr = Formatter.formatFileSize(this, availSize);
String ExternalSize = ”SD总存储空间:“+ totalStr + ”可使用的空间:“ + availStr;
return ExternalSize;} /* * 获取可用的内部存储 */ public String getRomSpaceInfo(){
File path = Environment.getDataDirectory();
StatFs stat = new StatFs(path.getPath());
long internalblockSize = stat.getBlockSize();
long internalblockcounts = stat.getBlockCount();
long internaltotalSize = internalblockSize*internalblockcounts;
String totalStr = Formatter.formatFileSize(this, internaltotalSize);
String RomSpaceInfo = ”可用的内存“+ totalStr;
} return RomSpaceInfo;} @Override public boolean onCreateOptionsMenu(Menu menu){ // Inflate the menu;this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}
28、sharedPreferences入门
->数据存储的API:用##分割用户名和密码的缺陷,真实存
储的话必须要把##转移成其他字符,sharePreferences
(共享参数)提供了一种方便存储数据的方式。
->在data目录下创建了一个xml文件,根节点是map,其实是以map集合来存
储的用户名和密码的对特殊字符进行了转义
package loginsharedPreference.service;
import android.content.Context;import android.content.SharedPreferences;import android.content.SharedPreferences.Editor;
/* * 保存用户名密码的的业务方法 */ public class LoginService { public static void SavaUserInfo(Context context,String username,String passwd){
//拿到上下文之后,有个方法叫getSharedPreferences
SharedPreferences sharedPreferences = context.getSharedPreferences(”config“, Context.MODE_PRIVATE);
Editor editor = sharedPreferences.edit();//得到sharedPreferences的编辑器
}
editor.putString(”username“,username);editor.putString(”passwd“,passwd);//类似于数据库的事物
editor.commit();//当前方法不会存在异常,所以设置为void } package loginsharedPreference;
import java.util.Map;
import loginsharedPreference.service.LoginService;import android.app.Activity;import android.content.SharedPreferences;import android.os.Bundle;import android.text.TextUtils;import android.view.Menu;import android.view.View;import android.widget.CheckBox;import android.widget.EditText;import android.widget.Toast;
import com.example.login.R;
public class MainActivity extends Activity {
private EditText et_number;private EditText et_passwd;private CheckBox cb_remPass;
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);//首先要把页面加载进来然后才有控件的获取
et_number =(EditText)findViewById(R.id.et_number);
et_passwd =(EditText)findViewById(R.id.et_passwd);
cb_remPass =(CheckBox)findViewById(R.id.cb_remPass);
SharedPreferences sharedPreferences = getSharedPreferences(”config“,MODE_PRIVATE);
String username = sharedPreferences.getString(”username“, ”“);
String passwd = sharedPreferences.getString(”passwd“, ”“);
et_number.setText(username);
et_passwd.setText(passwd);
}
@Override public boolean onCreateOptionsMenu(Menu menu){
// Inflate the menu;this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);
return true;} public void login(View v){
String number = et_number.getText().toString().trim();
String passwd = et_passwd.getText().toString().trim();
if(TextUtils.isEmpty(number)||TextUtils.isEmpty(passwd)){
Toast.makeText(this, ”登录名或者密码不能为空“, Toast.LENGTH_SHORT).show();
return;
}else{
if(cb_remPass.isChecked()){
//如果选择了保存用户密码,那么就保存用户密码
LoginService.SavaUserInfo(this,number, passwd);
Toast.makeText(this, ”保存用户信息成功“, Toast.LENGTH_SHORT).show();
}
//登陆发送消息到服务器,服务器验证是否正确
if(”zhangsan“.equals(number)&&”123456“.equals(passwd)){
Toast.makeText(this, ”登陆成功“, Toast.LENGTH_LONG).show();
}else{
Toast.makeText(this, ”登录失败,用户名或者密码不正确“, Toast.LENGTH_LONG).show();
}
} } }
29、xml文件的序列化
->一个小异常:如果没有识别这个设备,重启的话要记得吧adb杀掉->自己手动添加,这种方式效率低,容易出错->XmlSerializer:XML序列化生成器
30、采用pull解析xml文件
->用于对象的持久化,将对象写到硬盘中,需要用的时候再反序列化取出来。
所谓序列化其实就是将程序中的数据(对象)通过某种方式,保存到本地中。然后可以在程序关闭之后还保存程序的某个执行状态,方便在程序下次
执行的时候通过”反序列化“读取出来,并且能够还原数据的类型,从而延续程序退出时的状态。
一般来说,我们会使用序列化保存一些需要持久化的数据,当然如果这个数据会比较庞大的话,我们就直接使用数据库了!所以,序列化实际上目前很多领域用的已经不多了,大部分使用 都已被数据库替代了!
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。序列化的实现:将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStrea
->xml文件的解析方式:
->DOM一次将XML文件加载进内存,生成树状结构,在内存中对树状结构进
行操作,缺点是消耗内存大,->SAX解析:基于事件的方式,自上而下,事件下去了就不能解析了,优点
是速度快,效率高,缺点是不能倒退;
->android下增加了一种解析xml文件的方式,pull解析,类似于SAX解析,定义了一个指针,指向了文档的开头,得到指针,一个tag一个tag的解析下去
->利用类加载器走到文件->创建一个解析器:pullParse0
具体代码:
(MainActivity.java)package com.example.xml;
import java.util.List;
import org.w3c.dom.Text;
import com.example.xml.domain.WeatherInfo;import com.example.xml.service.WeatherService;
import android.support.v7.app.ActionBarActivity;import android.support.v7.app.ActionBar;import android.support.v4.app.Fragment;import android.app.Activity;import android.os.Bundle;import android.view.LayoutInflater;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import android.os.Build;
public class MainActivity extends Activity {
@Override protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv =(TextView)findViewById(R.id.tv);
List weatherInfos = WeatherService.getWeatherInfos(MainActivity.class.getClassLoader().getResourceAsStream(”weather.xml“));
StringBuilder sb = new StringBuilder();
for(WeatherInfo info:weatherInfos){
sb.append(info.toString()+”n“);
}
tv.setText(sb.toString());}
@Override public boolean onCreateOptionsMenu(Menu menu){
// Inflate the menu;this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);
return true;} }
(WeatherInfo.java)/** * */ package com.example.xml.domain;
import android.R.integer;/** * @author yonghen * */ public class WeatherInfo { private int id;private String name;private String wind;private String weather;private String temp;private String pm;/*(non-Javadoc)* @see java.lang.Object#toString()*/ @Override public String toString(){
return ”WeatherInfos [id=“ + id + ”, name=“ + name + ”, wind=“ + wind
+ ”, weather=“ + weather + ”, temp=“ + temp + ”, pm=“ + pm
+ ”]“;}
/** * @param id * @param name * @param wind * @param weather
* @param temp * @param pm */ public WeatherInfo(){ super();} public WeatherInfo(int id, String name, String wind, String weather,String temp, String pm){ super();this.id = id;this.name = name;this.wind = wind;this.weather = weather;this.temp = temp;this.pm = pm;} /** * @return the id */ public int getId(){ return id;} /** * @param id the id to set */ public void setId(int id){ this.id = id;} /** * @return the name */ public String getName(){ return name;} /** * @param name the name to set */ public void setName(String name){ this.name = name;} /** * @return the wind */
public String getWind(){ return wind;} /** * @param wind the wind to set */ public void setWind(String wind){ this.wind = wind;} /** * @return the weather */ public String getWeather(){ return weather;} /** * @param weather the weather to set */ public void setWeather(String weather){ this.weather = weather;} /** * @return the temp */ public String getTemp(){ return temp;} /** * @param temp the temp to set */ public void setTemp(String temp){ this.temp = temp;} /** * @return the pm */ public String getPm(){ return pm;} /** * @param pm the pm to set */ public void setPm(String pm){ this.pm = pm;
}
}
(WeatherService.java)/** * */ package com.example.xml.service;
import java.io.IOException;import java.io.InputStream;import java.util.ArrayList;import java.util.List;
import org.xmlpull.v1.XmlPullParser;import org.xmlpull.v1.XmlPullParserException;
import android.R.integer;import android.util.Xml;
import com.example.xml.domain.WeatherInfo;/** * @author yonghen * */ public class WeatherService { public static List getWeatherInfos(InputStream inputStream){
XmlPullParser xmlPullParser = Xml.newPullParser();
WeatherInfo weatherInfo = null;
List weatherInfos = null;
try {
xmlPullParser.setInput(inputStream, ”utf-8“);
int type = xmlPullParser.getEventType();//拿到的是当前的事件类型:
while(type!= xmlPullParser.END_DOCUMENT){
switch(type){
case XmlPullParser.START_TAG:
if(”info“.equals(xmlPullParser.getName())){//解析到全局开始的标签
weatherInfos = new ArrayList();
}else if(”city“.equals(xmlPullParser.getName())){
weatherInfo = new WeatherInfo();
String idString = xmlPullParser.getAttributeName(0);
weatherInfo.setId(Integer.parseInt(idString));//字符串转化成整型数据
}else if(”temp“.equals(xmlPullParser.getName())){
String temp = xmlPullParser.nextText();
weatherInfo.setTemp(temp);
}else if(”wind“.equals(xmlPullParser.getName())){
String wind = xmlPullParser.nextText();
weatherInfo.setWind(wind);
}else if(”name“.equals(xmlPullParser.getName())){
String name = xmlPullParser.nextText();
weatherInfo.setName(name);
}else if(”weather“.equals(xmlPullParser.getName())){
String weather = xmlPullParser.nextText();
weatherInfo.setName(weather);
}else if(”pm“.equals(xmlPullParser.getName())){
String pm = xmlPullParser.nextText();
weatherInfo.setPm(pm);
}
break;
case XmlPullParser.END_TAG:
if(”city“.equals(xmlPullParser.getName())){
weatherInfos.add(weatherInfo);
weatherInfo=null;
}
break;
}
type = xmlPullParser.next();
}
} catch(XmlPullParserException e){
// TODO Auto-generated catch block
e.printStackTrace();
} catch(IOException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
return weatherInfos;} }(Weather.xml)
20/30
5月20日 多云转晴
南风3-4
上海
200
20/30
5月19日 多云转晴
南风3-4
上海
200
20/30
5月18日 多云转晴
南风3-4
上海
200
20/30
5月17日 多云转晴
南风3-4
上海
200
31、采用断点调试的方法观察pull解析的的流程
->现在代码双单击添加断点
->debug as Android Application->然后打开调试视图
32、android下创建一个sqllite数据库
->SQLiteOpenHelper(数据库大概帮助类):数据库创建和打开的帮助类->
->PersonSQLiteOpenHelper.java /** * */ package com.example.sqlite;
import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteDatabase.CursorFactory;import android.database.sqlite.SQLiteOpenHelper;/** * @author yonghen * */ public class PersonSQLiteHelper extends SQLiteOpenHelper {
/**
* @数据库的构造方法,用来定义数据库的名称,数据库查询的结果集,数据库的版本 */ public PersonSQLiteHelper(Context context){//Context:上下文告诉数据库存放在什么位置,String name:数据库名,factory一般为null,设置系统默认的游标工厂,super(context, ”Person.db“, null, 1);
} /* * 数据库第一次被创建的时候调用的方法,db创建的数据库 */ @Override public void onCreate(SQLiteDatabase db){
db.execSQL(”create table person id integer primary antoincrement,name varchar(20),number varchar(20)");//底层存储类型都是String,(20)都是给程序员看的,其实没有影响
}
/*(non-Javadoc)* @see android.database.sqlite.SQLiteOpenHelper#onUpgrade(android.database.sqlite.SQLiteDatabase, int, int)*/ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){ } }
->TestPersonDB.java /** * */ package com.example.sqlite;
import android.database.sqlite.SQLiteAbortException;import android.database.sqlite.SQLiteDatabase;import android.test.AndroidTestCase;/** * @author yonghen * */ public class TestPersonDB extends AndroidTestCase { public void testCreateDB(){ PersonSQLiteHelper personSQLiteHelper = new PersonSQLiteHelper(getContext());//new出来一个对象,实际上数据库并未被真正的创建,测试框架提供了一个获取Context的方法
personSQLiteHelper.getWritableDatabase();//数据库才会被真正的创建出来, } }
33、sql语句实现数据库的增删改查
->javaweb:
->加载到jdbc的驱动;//android已经集成在framework->链接到数据库;//只要拿到数据库的引用
->准备sql语句 增删改查
->增加:insert into person(name,number)values('zhang','110')->删除:delete from person where name = 'zhangsan'->修改:update person set number = '119' where name = 'zhangsan'->查找:select * from person->查找具体:select * from person where name = 'zhangsan'
->PersonSQLiteHelper.java /** * */ package com.example.sqlite;
import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteDatabase.CursorFactory;import android.database.sqlite.SQLiteOpenHelper;/** * @author yonghen * */ public class PersonSQLiteHelper extends SQLiteOpenHelper {
/** * @数据库的构造方法,用来定义数据库的名称,数据库查询的结果集,数据库的版本
*/ public PersonSQLiteHelper(Context context){//Context:上下文告诉数据库存放在什么位置,String name:数据库名,factory一般为null,设置系统默认的游标工厂,
【黑马程序员】PHP课程同步笔记day18:PHP函数
PHP函数 1.概念
将一段常用的功能代码,进行封装,然后起个名字,叫”函数” 使用函数,可以减少我们的工作量。对于后期的项目维护,十分方便。2.函数定义格式
Function functionName(形参1,形参2,形参3......){
函数的功能代码
[return 参数r] } 函数语法格式说明:
Function是系统关键字,不分大小写。
functionName是自定义的函数名称。函数名的命名规则与变量一样,只是不加$符号。
()定义函数时的参数,该参数又称为”形参”。
形式参数:主要用来接收调用函数者,传递过来的数据。
形参可以是多个,多个形参之间用逗号隔开,也可以没有形参
形参其实就是一个变量的名称,主要用来临时存储数据的。{}是函数的功能代码。Return语句:
向谁返回内容?谁调用了该函数,就向谁返回。
返回什么内容?该内容的类型不限制,可以是任何数据类型
黑马程序员济南中心 编著
Return语句,一旦执行,函数将中止。也就是return语句之后的函数代码不再执行。
Return 语句返回一个值,并退出函数。
3.函数调用
函数定义是不会自动执行的。函数必须要经过调用,才能看到结果 调用函数和定义函数不分顺序。4.函数参数
a)形式参数(形参):形参主要用来接收调用函数传递过来的数据。
i.形参一般是变量,不能是具体的值
ii.形参只能在函数内部使用
b)实际参数(实参):向定义函数传递的数据
i.实参可以是具体值,也可以是一个变量
c)形参和实参的个数,一般情况下必须一致 Function showInfo($a){ Echo “OK”;} $a = 100;showInfo($a);函数参数传递 1.值传递(拷贝传值)将一个变量的值,”拷贝”一份,传给形参
黑马程序员济南中心 编著
在函数内部,对形参进行了修改,而函数外的这个变量不会改变 函数内的形参,与函数外的实参,是相互独立的,没有任何联系的
在PHP中,默认”值传递”的有:字符型、整型、浮点型、布尔型、数组、NULL
2.引用传递
将一个变量的地址传给形参,即形参与变量指向的是”同一物”.变量和参数之间是相互联系,修改一个,另一个会跟着变。
参数在使用引用传递时,需要在”形参”前加一个”&”符号。”实参”前不能添加。
默认引用传地址:资源和对象
黑马程序员济南中心 编著
3.默认参数
PHP支持默认参数。
当实参格式少于形参个数时,那么少的那个实参可以用末日的形参来代替
匿名函数
1.概念
没有名字的函数就是匿名函数,它不能单独定义也不能单独调用 匿名函数一般用来给其他变量赋值的。
黑马程序员济南中心 编著
2.匿名函数的两种用法
i.将匿名函数当成一个数据,赋给其他变量
ii.将匿名函数作为函数的参数来使用
变量作用域
变量作用域:就是变量生效的范围
在PHP中三种变量作用域:全局变量、局部变量、超全局变量。1.全局变量
全局变量:在函数外部定义的变量,称为”全局变量”。
黑马程序员济南中心 编著
全局变量,在网页执行完毕,就消失了。在JS中,全局变量,可以直接在函数内部来使用 在PHP中,全局变量不能直接在函数内部使用 2.局部变量
局部变量:在函数内部定义的变量,称为”局部变量”。局部变量,只能在函数内部来使用 局部变量,在函数执行完毕后就消失了。3.在局部作用域中访问全局变量---global关键字
Global关键字,只能在函数内部来使用
不能在使用global关键字时,直接给变量赋值。只能是先声明为全局,再赋值。
$GLOBALS超全局数组
“超全局数组变量”可以在网页的任何地方使用,包括函数内部和函数外部。$GLOBALS超全局数组中包含的内容有:$_GET、$_POST、$_COOKIE、$_FILES
黑马程序员济南中心 编著
【黑马程序员】PHP课程同步笔记day17:数组介绍
数组 1.数组的概念
数组是一组值的集合,变量是单个值的容器,而数组是多个值的容器 2.数组的分类
1.枚举数组:数组的下标是从0开始的正整数
2.关联数组:数组的下标可以是字符串
$arr = array(“db_host” => “localhost”, “db_user” => “root”, “db_pwd” =>”root”,);
3.混合数组:下标既有整型的,也有字符串的
$arr = array(“db_host” => “localhost”, “db_user” => “root”, “db_pwd” =>”root”, “黑马程序员”, “济南分校”);
4.多维数组:数组的元素的值的类型是一个数组。数组套数组。数组元素的下标只能是正整数和字符串。数组元素的值,可以是任何类型,当然可以是数组。
黑马程序员济南中心 编著
$arr = array(Array(10,11,12,13), Array(20,21,22), Array(30,31), TRUE,NULL);3.数组的创建
a)使用array()来创建数组 $arr = array([$key=>]$value, [$key=>]$value, [$key=>]$value,.....);语法说明:
$key代表数组元素的下标,可以省略。
$key的类型可以是整型和字符型,如果$key省略,默认的数组应该是枚举数组。$value代表数组元素的值,值可以是任何类型。“=>”重载下标,或者重新指定下标。多个数组元素之间用英文下的逗号隔开。b)使用[]创建数组的语法
语法1:$arr[] = $value
黑马程序员济南中心 编著
说明: 1)如果数组不存在,则会创建一个数组 2)第一个元素就是下标为0的元素 3)如果数组存在,则相当于添加一个新元素 4)新元素的下标,应该是最大整数下标+1 语法2: $arr[$key] = $value 说明:
1)同时指定下标,指定的下标是多少,就是多少。2)如果指定的数组不存在,也会创建一个数组 3)如果指定的数组存在,则添加一个新元素 $arr[] = 100;$arr[] = 200;$arr[5] = 500;$arr[“a”] = “abc”;多维数组
1、使用array()来创建多维数组
$arr = array(Array(10,11,12,13,14), Array(20,21,22,23), Array(30,31,32), Array(Array(40,41),黑马程序员济南中心 编著
Array(42,43)));
2、使用[]来创建多维数组
$arr[“name”] = “Mary”;$arr[“sex”] = “男”;$arr[“contact”][“tel”] = “11111111111”;$arr[“contact”][“qq”] = “11233321”;$arr[] = array(10,20,30);实例:用表格输出二维数组 $arr = array(Array(“10010”,”Mary”,”大专”,”传智专修学院”), Array(“10020”,”Kate”,”大专”,”传智专修学院”), Array(“10030”,”James”,”大专”,”传智专修学院”), Array(“10040”,”Kobe”,”大专”,”传智专修学院”),);$str = “”;$str.= “
” For($i = 0;$i”;For($j=0;$j”.$arr[$i][$j].””;黑马程序员济南中心 编著
} $str.= “”;} $str.= “
”;Echo $str;数组操作函数 1.print_r()a)描述:打印变量信息
b)语法:print_r(mixed $expression)c)说明:如果给出的是string、interger或float,将打印变量值本身。如果给出的是array,将会按照一定格式显示键和元素
2.Count()a)描述:统计数组有效数据的个数
b)说明:计算数组中的单元数目或对象中的属性个数。c)语法:int count(mixed $var)d)参数:$mode是否统计多维数组中的个数 3.Unset()a)描述:删除变量或数组元素或者对象属性 b)语法:void unset(mixed $var)c)返回值:无
d)注意:如果删除变量的话,只是删除变量名称和到值之间的指向。如果删除数组元素的话,值会被删除,而下标还在。如果删除整个数组的话,而整个数组都不存在黑马程序员济南中心 编著
了。
实例:求一维数组中元素的平均值 $arr = array(1,2,3,4,5,6,7,8);$num = 0;$len = count($arr);For($i=0;$i<$len;++$i){ $sum += $arr[$i];} Echo “平均值为:”.$sum/$len;实例:求二维数组中元素的平均值 $arr = array(Array(10,11,12,13,14), Array(20,21,22,23), Array(30,31,32), Array(40,41), Array(50));$sum = 0;$len = 0;For($i = 0;$i黑马程序员济南中心 编著
$len ++;} } Echo “平均值:”.round($sum/$len,2);实例:求一维数组中的最大值 $arr = array(9,2,3,45,5,7);$max = $arr[0];For($i=0;$iIf($max<$arr[$i]){
黑马程序员济南中心 编著
$max = $arr[$i];$max_index = $i;} //最小值
If($min>$arr[$i]){ $min = $arr[$i];$min_index = $i;} } //交换最大值和最小值的位置 $arr[$max_index] = $min;$arr[$min_index] = $max;数组遍历:foreach 语法结构:
Foreach($arr as [$key=>]$value){循环体代码} 语法结构说明:
$arr代表当前要遍历的数组名称 As是系统关键字
$key表示每一次取到元素的键名,可以省略 $value表示每一次取到元素的键值 如果数组指针指到数组的末端,则退出循环 实例:foreach遍历一维数组
黑马程序员济南中心 编著
$arr = array(“name” => “Mary”, “sex” => “男”, “age” => 24);Foreach($arr as $key=>$value){ Echo “$arr[$key]=$value ”;} 实例:foreach遍历二维数组 $arr = array(“a” =>array(“10010”,”Mary”,”男”,24), “b”=>array(“10020”,”Kate”,”女”,20), “c” => array(“10030”,”Kobe”,”男”,40));$str = “”;$str.=”
”;Foreach($arr as $arr2){ $str.=””;Foreach($arr2 as $value){ $str.=”$value ”;} $str.=” ”;黑马程序员济南中心 编著
} $str.=”
”;Echo $str;实例:foreach 中的$value引用传地址 $arr = array(1,2,3,4,5,6,7,8);Foreach($arr as &$value){ $value *=2;} Var_dump($arr);数组操作函数 1.each()a)描述:返回数组中当前的键/值对(数组元素)并将数组指针向前移动一步 b)语法:array each(array &$array)c)返回值:返回array数组中当前指针位置的键/值对并向前移动数组指针。键值对被返回四个单元的数组。单元0和key包含有数组单元的键名,1和value包含有数据。
2.List()a)描述:把数组中的值(前几个值)赋给一些变量 b)语法:array list(mixed $varname)c)举例:list($name,$sex,$age)= array(“Kobe”,”男”,24,”高中”);i.说明:将数组中前三个元素的值,赋给list函数中的三个变量。
ii.数组中多余的值不需要
黑马程序员济南中心 编著
iii.要求数组必须是枚举数组,下标必须是从0开始的正整数 iv.下标必须是连续的,中间不能断档。
黑马程序员济南中心 编著