(1)自定义控件、UI设计、常用动画特效
1)自定义控件
①为什么要自定义控件?
Android本身提供了很多控件,但是这些控件并不能满足我们所有的要求,现在用户的要求越来越高,这就要求我们做出的软件
除了功能要齐全外,还要给用户比较炫比较人性化的体验,这个时候就需要我们自定义控件来提高用户体验。
现在用户体验是炒得比较火的一个概念,各大网站各个软件都在说提高用户体验。
Android中的控件都是继承自View类,通过重写onDraw方法来绘制我们所需的控件。
②如何实现自定义控件?
实现自定义控件的两种方式:
第一是继承已有控件,通过重写相关方法来实现我们的需求
第二是继承View类或者ViewGroup类来绘制我们需要的控件
注:一般来讲,通过继承已有的控件来实现自定义控件简单一点,开发中常用继承已有控件来实现自定义控件。
③ListView:
a、ListView的作用是什么?
显示数据
b、ListView如何用?
首先要给ListView设置一个适配器Adapter,把要显示的数据交给适配器Adapter去处理,
另外ListView的getView方法每被调用一次显示一个条目,都伴随着一个旧的条目被移除,故为了优化ListView,
可以在getView()方法中重用旧条目convertView
还有ListView的getView方法中每执行一次findViewById方法时,都会加载相应布局的树状结构,再遍历该树状结构找到指定id,
当该布局的树状结构很复杂时,每次都查找id会比较麻烦,所以为了优化我们可以提供一个ViewHolder类,
用来记录布局中的所有控件,这样布局中的控件id只需查找一次,再用时,直接在ViewHolder类里面取
最后用ListView显示大数据时,还需要进行分批加载或分页显示处理
3)动画特效:
①动画的分类:
安卓中的动画分为两种,一种是帧动画(Frame),一种是渐变动画(Tweened)
渐变动画又分为四种动画类型,Alpha、Scale、Translate和Rotate
(2)网络数据传输,熟悉多线程、Socket网络编程、熟悉TCP、UDP、HTTP等协议
1)网络编程概述:
①网络模型:
****OSI模型
应用层
表示层
会话层
传输层
网络层
数据连接层
物理层
****TCP/IP模型
应用层
传输层
网际层
主机至网络层
②网络通讯要素
IP地址
端口号
传输协议
③网络通讯前提:
**找到对方IP
**数据要发送到指定端口。为了标示不同的应用程序,所以给这些网络应用程序都用数字进行标示这个表示就叫端口
**定义通信规则。这个规则称为通信协议,国际组织定义了通用协议TCP/IP
1)Android网络应用的概述:
Android完全支持JDK本身的TCP、UDP网络通信API,可以使用Socket、ServerSocket来建立基于TCP/IP协议的网络通信;
也可以使用DatagramSocket/Datagrampacket来建立基于UDP协议的网络通信。
同时Android还支持JDK提供的URL、URLConnection等网络通信的API。
2)TCP和UDP的区别:
①UDP协议:
面向无连接
每个数据报的大小在限制在64k内
因为是面向无连接,所以是不可靠协议
不需要建立连接,速度快
②TCP协议:
必须建立连接,形成传输数据的通道
在连接中可进行大数据量传输
通过三次握手完成连接,是可靠协议
必须建立连接,效率会稍低
注:三次握手:
第一次:我问你:在么?
第二次:你回答:在。
第三次:我反馈:哦,我知道你在。
3)Socket:
**Socket就是为网络服务提供的一种机制
**通信的两端都有Socket
**网络通信其实就是Socket间的通信
**数据在两个Socket间通过IO传输
**玩Socket主要就是记住流程,代码查文档就行
4)UDP(User Datagram Protocol):用户数据协议
①UDP概述:
需要DatagramSocket与DatagramPacket对象来实现UDP协议传输数据
UDP协议是一种面向无连接的协议。面向无连接的协议指的是正式通信前不必与对方先建立连接,不管对方连接状态就直接发送数据。
②UDP协议开发步骤:
**发送端:
建立DatagramSocket服务;
提供数据,并将数据封装到字节数组中;
创建DatagramPacket数据包,并把数据封装到包中,同时指定接收端IP和接收端口
通过Socket服务,利用send方法将数据包发送出去;
关闭DatagramSocket和DatagramPacket服务。
**接收端:
建立DatagramSocket服务,并监听一个端口;
定义一个字节数组和一个数据包,同时将数组封装进数据包;
通过DatagramPacket的receive方法,将接收的数据存入定义好的数据包;
通过DatagramPacke关闭的方法,获取发送数据包中的信息;
关闭DatagramSocket和DatagramPacket服务。
③UDP协议的Demo(必须掌握):
****发送端:
class UDPSend
{
public static void main(String[] args) throws Exception
{
DatagramSocket ds = new DatagramSocket();
byte[] buf = "这是UDP发送端".getBytes();
DatagramPacket dp = new DatagramPacket(
buf,buf.length,InetAddress.getByName("192.168.1.253"),10000);
ds.send(dp);
ds.close();
}
}
****接收端
class UDPRece
{
public static void main(String[] args) throws Exception
{
DatagramSocket ds = new DatagramSocket(10000);
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
ds.receive(dp);//将发送端发送的数据包接收到接收端的数据包中
String ip = dp.getAddress().getHosyAddress();//获取发送端的ip
String data = new String(dp.getData(),0,dp.getLength());//获取数据
int port = dp.getPort();//获取发送端的端口号
sop(ip+":"+data+":"+port);
ds.close();
}
}
注:协议的概念和作用:
什么是协议?
网络通信的一种规则
协议的作用?
保证通信两端实现网络通信
5)TCP/IP协议:Socket和ServerSocket
①基于TCP协议的网络通信概述:
TCP/IP通信协议是一种必须建立连接的可靠的网络通信协议。它在通信两端各建立一个Socket,从而在通信的两端之间形成网络虚拟链路。
网络虚拟链路一旦建立,两端的程序就可以进行通信。
②TCP/IP协议开发步骤:
**客户端:
建立Socket服务,并指定要连接的主机和端口;
获取Socket流中的输出流OutputStream,将数据写入流中,通过网络发送给服务端;
获取Socket流中的输出流InputStream,获取服务端的反馈信息;
关闭资源。
**服务端:
建立ServerSocket服务,并监听一个端口;
通过ServerSocket服务的accept方法,获取Socket服务对象;
使用客户端对象的读取流获取客户端发送过来的数据;
通过客户端对象的写入流反馈信息给客户端;
关闭资源
③TCP/IP协议的一个Demo(必须要掌握!):
客户端:
class TCPClient
{
public static void main(String[] args)
{
Socket s = new Socket("192.168.1.253",10000);
OutputStream os = s.getOutputStream();
out.write("这是TCP发送的数据".getBytes());
s.close();
}
}
服务端:
class TCPServer
{
public static void main(String[] args)
{
ServerSocket ss = new ServerSocket(10000);
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
sop(ip);
InputStream is = s.getInputStream();
byte[] buf = new byte[1024];
int len = is.read(buf);
sop(new String(buf,0,len));
s.close();
ss.close();
}
}
6)HTTP协议:
a、HTTP是Hyper Text Transfer Protocol的缩写
b、是由W3C制定和维护的。目前版本为1.0和1.1
c、是开发web的基石,非常地重要
d、1.0版本:是无状态的协议,即一次连接只响应一次请求,响应完了就关闭此次连接
要想再访问须重新建立连接。而连接都是比较耗资源的。
1.1版本:是有状态的协议。即可以在一次网络连接基础上发出多次请求和得到多次的响应。
当距离上次请求时间过长时,服务器会自动断掉连接,这就是超时机制。
①HTTP协议的组成:
请求部分:
请求行:
GET / HTTP/1.1 包含:请求方式GET 请求的资源路径:/ 协议版本号:HTTP/1.1
请求方式。常用的有GET、POST
GET方式:默认方式。直接输入的网址。
表单数据出现在请求行中。url?username=abc&password=123
特点:不安全;有长度限制:<1k
POST方式:可以通过表单form method="post"设置
表单数据会出现在正文中。
特点:安全;没有长度限制
请求消息头:
请求正文:第一个空行之后的全部都是请求正文
响应部分:
响应行:
HTTP/1.1 200 OK 包含:协议版本号:HTTP/1.1 响应码:200 描述:OK
响应码:(实际用到的30个左右,其他都是W3C保留的)
描述:对响应码的描述
常用响应码:
200:一切正常
302/307:请求的资源路径变更了
304:资源没有被修改过
404:资源不存在,找不到资源
500:服务器程序有错
响应消息头:
响应正文:
第一个空行之后的全部都是响应正文,浏览器显示的就是正文中的内容
7)网络通信中加入多线程:
①TCP/IP协议:
实际应用中,服务端需要不断的读取客户端数据和写入数据到客户端;而客户端也需要不断的读取服务端数据和写入数据到服务端。
当使用传统的BufferedReader的readLine()方法读取数据时,由于该方法是阻塞式方法,故当该方法成功返回之前,线程被阻塞,
程序无法继续执行。居于此,服务器应该为每个Socket单独开启一条线程,每个线程负责与一个客户端进行通信。
客户端应该包含两条线程,一条负责生产主界面、相应用户动作并将用户输入的数据写入到Socket对应的输出流中
另一条负责读取Socket对应输入流中从服务器端发送过来的数据,并负责将这些数据在主界面上显示。
使用NIO实现非阻塞Socket通信(JDK 1.4以后开始):
使用NIO API可以让服务器端使用一个或者有限个线程来同时处理连接到服务端的所有客户端,如多人聊天室
使用AIO(Asynchronous IO)实现非阻塞通信(JDK 1.7开始):
通过支持异步Channel来实现
②多线程应用:
a、多线程的作用:提高效率
b、多线程的应用:
多线程下载:
创建URL对象
获取指定URL对象所指向的资源的大小(getConnectionLength())
在本地磁盘上创建一个与网络资源大小相同的空文件:RandomAccessFile.setLength()
计算每条线程应该下载网络资源的哪个部分(从哪个字节开始到哪个字节结束)
依次创建、启动多线程来下载网络资源的指定部分
//执行如下代码设置请求头,确定指定线程下载的部分;如果不设置该头,则每个线程都从头下载到末尾
HttpURLConnection.setRequestProperty("Range","bytes="+start+"-"+end);
多线程断点续传下载:
开始下载时,判断是否是新的下载任务
如果是,从头开始下载
如果不是,找到上次下载完成多少,继续下载
下载过程中记录每条线程的下载进度,同时下载多少就写多少到本地,并且每次向文件中写入数据之后,在数据库中更新下载进度
下载完成之后删除数据库中下载记录
8)网络通信中的URL编程:
①URL概述:
URL(Uniform Resource Locator)对象代表统一资源定位器,是指向网络资源的指针。网络资源可以是简单的文件或者目录,
也可以是复杂的对象的引用,例如对数据库或搜索引擎的查询。
②URL组成:
由协议名、主机、端口和资源路径组成。如Http://localhost:8080/BookShop/index.jsp
③URL的应用:
使用URL访问网络资源:
使用URLConnection提交请求:
通过URL.openConnection()创建URLConnection对象
设置URLConnection对象的参数和普通请求属性
发送GET或者POST请求
使用HttpURLConnection访问网络资源:
(3)Handler消息传递机制和Android下的消息推送机制:
1)Handler消息传递机制:
①Handler概述:
Handler是界面刷新机制
Handler是用来解决Android应用多线程间通信问题,主线程和子线程之间通信问题
Android系统不允许Activity新启动的线程访问该Activity里面的界面组件。这就导致新启动的线程无法动态改变该界面组件的属性值。
即主线程创建View,但无法获取数据;新线程有数据,但无法修改View。Handler消息传递机制就可以解决此类问题。
②Handler的作用:
a、Handler用在一个线程中,Handler的作用就是实现异步操作;
b、Handler用在不同线程中,Handler的作用就是实现异步操作和实现线程间通信。
③Handler和Looper的关系:
a、Handler主要是用来发送和处理消息,但是发送了消息后,消息是怎么传递的呢?
这就是Looper的作用了,每个Handler内部都会封装一个Looper对象,如果在创建Handler的时候不指定Looper对象,
系统就会默认将当前线程的Looper绑定到Handler上,
Looper对象中维护者一个消息队列,Hander发送的消息都会存储到这个消息队列中,
Looper不断的遍历这个消息队列,取出消息,交给handleMessage方法处理,
Looper属于哪个线程,hadleMessage方法就会在那个线程中执行。
b、Looper对象的作用:
Looper负责管理线程的消息队列和消息循环
**主线程的Looper对象:
当在主线程中使用Handler的时候,不用指定Looper,因为在主线程开启的时候,就已经调用了Looper.loop()方法开始轮询了。
通过Handler.getLooper()可获取当前主线程的Looper对象
主线程可通过Looper对象给子线程发送消息
**子线程的Looper对象:
在子线程中使用Handler的时候,通过调用Looper的prepare方法创建存储Looper对象,还得调用Looper.loop()方法开启轮询。
一个线程可以存在(当然也可以不存在)一个消息队列和一个消息循环(Looper),特定线程的消息只能分发给本线程,
不能进行跨线程、跨进程通讯。但是创建的工作线程默认是没有消息循环和消息队列的,如果想让该线程具有消息队列和消息循环,
需要在线程中首先调用Looper.prepare()来创建消息队列,然后调用Looper.loop()进入消息循环。
注:Android中除了进度条,其他View在创建该View的线程中修改。
④Handler如何使用:
Handler的使用需要四个对象配合使用:
Handler、Looper、Message和Thread
⑤Handler和AsyncTask的区别:
a、相同点:
AsyncTask和Handler都能通过主线程和子线程之间的通信更新主界面
b、不同点:
Handler比较麻烦,而AsyncTask使任务更加方便,而且AsyncTask过程可控;
对于多个后台任务时,使用Handler代码结构清晰简单;而使用多个AsyncTask时容易发生异常。
2)Android下的消息推送机制:
①消息推送机制概述:
当我们开发和服务器交互的应用时,基本上都需要获取服务端的数据,这就需要消息推送机制来实现。
②获取服务器上不定时更新的信息的两种方式:
第一种是客户端使用Pull(拉)的方式,客户端每隔一段时间去服务端获取信息,看是否有更新的信息,有就获取
第二种是服务端使用Push(推)的方式,服务端更新数据了,就把更新的数据Push到客户端
注:虽然Pull和Push方式都能实现获取服务端更新的数据的功能,但明显的Push方式比Pull更节省用户的流量和电量
③消息推送解决方案:
****轮循Pull:
应用程序阶段性的与服务器进行连接并查询是否有新消息
缺陷:要考虑轮询的频率,如果太慢可能导致某些消息的延迟,如果太快,则会大量消耗网络带宽和电池
****SMS Push:
通过拦截SMS消息并且解析消息内容来了解服务器的意图
缺陷:成本相对比较高,你很难找到免费的短消息发送网关
****持久连接Push:
缺陷:很难在手机上实现一个可靠的服务,并且非常消耗手机的电池
④消息推送服务:
****C2DM(Cloud to Device Messaging)服务:
C2DM是Google提供的消息推送服务,是一个简单的、轻量级的机制,允许服务器可以通知移动应用程序直接与服务器进行通信
以便于从服务器获取应用程序更新和用户数据。
C2DM服务负责处理诸如消息排队等事务并向运行于目标设备上的应用程序分发这些消息。
C2DM服务的问题:
C2DM内置于Android的2.2系统上,无法兼容老的1.6到2.1系统
C2DM需要依赖于Google官方提供的C2DM服务器,由于国内的网络环境,这个服务经常不可用,如果想要很好的使用,
我们的App Server必须也在国外,这个恐怕不是每个开发者都能够实现的
****MQTT协议实现Android推送:
MQTT是一个轻量级的消息发布/订阅协议,它是实现基于手机客户端的消息推送服务器的理想解决方案
wmqtt.jar 是IBM提供的MQTT协议的实现
****RSMB实现推送:
Really Small Message Broker (RSMB) ,他是一个简单的MQTT代理,同样由IBM提供
****XMPP协议实现Android推送:
Google官方的C2DM服务器底层也是采用XMPP协议进行的封装
XMPP(可扩展通讯和表示协议)是基于可扩展标记语言(XML)的协议,它用于即时消息(IM)以及在线探测。
这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息
androidpn是一个基于XMPP协议的java开源Android push notification实现
注:
XMPP协议实现Android推送的最大优势就是简单,我们不需要象C2DM那样依赖操作系统版本,也不会担心某一天Google服务器不可用。
利用XMPP协议我们还可以进一步的对协议进行扩展,实现更为完善的功能。采用这个方案,我们目前只能发送文字消息,
不过对于推送来说一般足够了,因为我们不能指望通过推送得到所有的数据
3)多线程间通信
①进程和线程以及多线程的概念:
进程:正在进行的程序。每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元
线程:进程内部的一条执行路径或者一个控制单元
注:两者的区别:
一个进程至少有一个线程
进程在执行过程中拥有独立的内存单元,而多个线程共享一个内存单元
多线程:
一个进程中有多个线程,称为多线程
②多线程的优势和弊端:
优势:解决了多部分同时运行的问题,提高效率
弊端:线程太多会导致效率的降低,因为线程的执行依靠的是CPU的来回切换
③实现多线程的方法:
实现多线程可以通过继承Thread类和实现Runnable接口
a、继承Thread
定义一个类继承Thread类
复写Thread类中的public void run()方法,将线程的任务代码封装到run方法中
直接创建Thread的子类对象,创建线程
调用start()方法,开启线程(调用线程的任务run方法)
b、实现Runnable接口;
定义一个类,实现Runnable接口;
覆盖接口的public void run()的方法,将线程的任务代码封装到run方法中;
创建Runnable接口的子类对象
将Runnabl接口的子类对象作为参数传递给Thread类的构造函数,创建Thread类对象
(原因:线程的任务都封装在Runnable接口子类对象的run方法中。
所以要在线程对象创建时就必须明确要运行的任务)。
调用start()方法,启动线程。
注:两种方法区别:
(1)实现Runnable接口避免了单继承的局限性
(2)继承Thread类线程代码存放在Thread子类的run方法中
实现Runnable接口线程代码存放在接口的子类的run方法中;
在定义线程时,建议使用实现Runnable接口,因为几乎所有多线程都可以使用这种方式实现
④线程的几种状态:
新建:new一个Thread对象或者其子类对象就是创建一个线程,当一个线程对象被创建,但是没有开启,这个时候,
只是为线程对象开辟了内存空间和初始化数据。
就绪:新建的对象调用start方法,就开启了线程,线程就到了就绪状态。
在这个状态的线程对象,具有执行资格,没有CPU执行权。
运行:当线程对象获取到了CPU的资源。
在这个状态的线程对象,既有执行资格,也有执行权。
冻结:运行过程中的线程由于某些原因(比如wait,sleep),释放了执行资格和执行权。
当然,他们可以回到运行状态。只不过不是直接回到运行状态,而是先回到就绪状态。
死亡:当线程对象调用的run()方法结束,或者直接调用stop()方法,就让线程对象死亡,线程对象在内存中变成了垃圾。
⑤多线程安全问题:
a、原因:
当程序的多条语句在操作线程的共享数据时(如买票例子中的票就是共享资源),由于线程的随机性导致
一个线程执行多条语句时,执行了一部分还没执行完,另一个线程抢夺到cpu执行权参与进来执行,
此时就导致共享数据发生错误。比如买票例子中打印重票和错票的情况。
b、解决方法:对多条操作共享数据的语句进行同步,一个线程在执行过程中其他线程不可以参与进来
⑥Java中多线程同步:
a、同步的作用:
同步是用来解决多线程的安全问题的,在多线程中,同步能控制对共享数据的访问。
如果没有同步,当一个线程在修改一个共享数据时,而另外一个线程正在使用或者更新同一个共享数据,这样容易导致程序出现错误的结果
b、同步的前提:
必须保证有两个以上线程
必须是多个线程使用同一个锁,即多条语句在操作线程共享数据
必须保证同步中只有一个线程在运行
c、同步的好处和弊端
好处:同步解决了多线程的安全问题
弊端:多线程都需要判断锁,比较消耗资源
d、同步的两种表现形式:
同步代码块:
可以指定需要获取哪个对象的同步锁,使用synchronized的代码块同样需要锁,但他的锁可以是任意对象
考虑到安全问题,一般还是使用同一个对象,相对来说效率较高。
注意:
**虽然同步代码块的锁可以使任何对象,但是在进行多线程通信使用同步代码快时,
必须保证同步代码快的锁的对象唯一,否则会报错。
**同步函数的锁是this,也要保证同步函数的锁的对象和调用wait、notify和notifyAll的对象是
同一个对象,也就是都是this锁代表的对象。
格式:
synchronized(对象)
{
需同步的代码;
}
同步函数
同步方法是指进入该方法时需要获取this对象的同步锁,在方法上使用synchronized关键字,
使用this对象作为锁,也就是使用了当前对象,因为锁住了方法,所以相对于代码块来说效率相对较低。
注:静态同步函数的锁是该方法所在的类的字节码文件对象,即类名.class文件
格式:
修饰词 synchronized 返回值类型 函数名(参数列表)
{
需同步的代码;
}
⑦死锁
两个线程对两个同步对象具有循环依赖时,就会发生死锁。
即同步嵌套同步,而锁却不同。
⑧为什么要线程间通信:
多线程并发执行的时候, 如果需要指定线程等待或者唤醒其他线程, 那么就需要线程间通信。
比如生产者消费者的问题,生产一个消费一个,生产的时候需要负责消费的进程等待,生产一个后完成后需要唤醒负责消费的线程,
同时让自己处于等待,消费的时候负责消费的线程被唤醒,消费完生产的产品后又将等待的生产线程唤醒,
然后使自己线程处于等待。这样来回通信,以达到生产一个消费一个的目的
⑨线程间怎么通信
在同步代码块中, 使用锁对象的wait()方法可以让当前线程等待, 直到有其他线程唤醒为止.
使用锁对象的notify()方法可以唤醒一个等待的线程,或者notifyAll唤醒所有等待的线程.
多线程间通信用sleep很难实现,睡眠时间很难把握。
⑩Android开发中线程间通信应用案例:
a、Handler
b、Intent
注:进程间通信案例:
服务、广播接收者、内容提供者等
(4)SQLite、MySql等数据库的CRUD及SharedPreferences的数据持久化
1)SQLite:
①SQLite概述:
Android平台中嵌入了一个关系型数据库SQLite,和其他数据库不同的是SQLite存储数据时不区分类型
SQLite是手机自带的数据库,每一个数据库就是一个XML文件,每一个XML文件有一张或多张表
②创建SQLite数据库步骤:
a、定义类继承SQLiteOpenHelper
SQLiteOpenHelper是用来打开数据库的一个工具,其中有创建onCreate()数据库和升级upGrade()数据库方法,
在获取数据库连接时,这些方法会自动执行,使用手机自带的SQLite数据库必须创建一个SQLiteOpenHelper子类,
实现其onCreate(SQLiteDatabase), onUpgrade(SQLiteDatabase, int, int)方法,
如果数据库不存在则创建,存在则检查数据库版本是不是最新,不是最新则升级数据库版本,维护其保持一个最佳的状态
b、获取数据库SQLiteDatabase对象
SQLiteOpenHelper. getWritableDatabase():获取写数据库,当可写时可获取读数据库
SQLiteOpenHelper. getReadableDatabase():获取读数据库
c、执行数据库增删改查操作
执行增删改操作,无返回结果集:
SQLiteDatabase.execSQL(String sql,Object[] params);
执行查询操作:返回Cursor结果集
SQLiteDatabase.rawQuery(String sql,String[] params);
或者执行CRUD操作:
SQLiteDatabase.insert();
SQLiteDatabase.update();
SQLiteDatabase.delete();
SQLiteDatabase.query();
d、关闭资源:(可选操作,每次获取数据库的时候数据库底层会自动关流,建议手动关闭)
SQLiteDatabase.close();
Cursor.close();
2)MySql:
①MySql概述:
结构化查询语言,Structured Query Language的缩写
②JDBC简介:
a、JDBC:java数据库连接,Java DataBase Connectivity的缩写
b、开发人员安装了不同的数据库服务器(如MySQL和Oracle),则需要安装不同的数据库驱动,
才能在java应用程序中连接该数据库并对该数据库的数据进行操作,而这样对开发人员来说是很麻烦的
于是乎SUN就提供了一套操作数据库的规范,该规范就是JDBC
不同数据库厂商实现了该规范(驱动),开发人员只要按照该规范开发就行了
c、JDBC规范的类在JDK中的
③JDBC编程步骤:
a、注册驱动:
方式一:DriverManager.registDriver(new com.mysql.jdbc.Driver())
注意该Driver所在的包是com.mysql.jdbc.*,而不是java.sql.*包中
该种方式不建议使用,原因如下:
****严重依赖具体的数据库驱动程序,DriverManager是java.sql.*包中的
如果改用Orcal数据库,则得改程序
****会导致数据库的驱动程序注册2次,DriverManager在类一加载的时候
就注册了一次,后面再new com.mysql.jdbc.Driver()又注册一次
(查看源代码)
方式二:Class.forName("com.mysql.jdbc.Driver");
开发用此方式,次方式避免了a中方式一出现的问题
b、建立与数据库的链接:java.sql.Connection,所有的与数据库的交互都必须在链接的基础上进行操作
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day12","root", "xiaruri");
注:url的固定格式写法要记住:"jdbc:mysql://localhost:3306/day12"
jdbc:代表协议 mysql:代表子协议 localhost:3306:代表主机和端口 day12:代表数据库
root:代表MySQL服务器用户名 xiaruri:用户名密码
实际开发中需把传进去的三个字符串抽取出来,写成配置文件,通过读取配置文件形式
将读取到的传进去,这样避免换数据库时改程序,只需改配置文件即可
c、获取代表SQL语句对象
Statement stmt = conn.createStatement();
d、执行SQL语句
String sql = "select id,name,password,email,birthday from users";
e、如果有结果集,会被封装成一个ResultSet对象
ResultSet rs = stmt.executeQuery(sql);
f、遍历结果集
while(rs.next()){
//rs.getObject(1):结果中每条记录的列索引从1开始。开发JDBC框架时使用
System.out.println(rs.getObject("id")+"\t"+rs.getObject("name")+"\t"+
rs.getObject("password")+"\t"+rs.getObject("email")+
"\t"+rs.getObject("birthday"));
}
h、关闭使用的资源
rs.close();
stmt.close();
conn.close();
④开源的数据源框架:
a、可直接访问硬件
b、DBCP
DBCP是Apache软件基金组织下的开源连接池实现,使用DBCP数据源应用程序应在系统中增加如下两个jar文件:
Commons-dbcp.jar:连接池的实现
Commons-pool.jar:连接池实现的依赖库
常用O-R Mapping映射工具
Hibernate CMP JPA(Java Persistent API)
Ibatis(后来改名为MyBatis)
Commons DbUtils(只是对JDBC简单封装)
Spring JDBC Template
DbUtils简介:
QueryRunner
MyBatis简介:
MyBatis的前身就是iBatis。她是一个数据持久层框架
MyBatis支持普通SQL查询、存储过程和高级映射的优秀持久层框架
消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索,MyBatis使用简单的XML或注解用于配置和原始映射
将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录
c、C3P0
3)SharedPreferences:
SharedPreferences对象就相当于一个可持久化的Map集合
通过put方法存储持久化数据,需要commit才有效
通过get获取持久化数据
(5)系统MediaPlayer的生命周期、图像、音频和视频多媒体开发技术
①MediaPlayer:最终播放音频、视频文件的都是通过MeidaPlayer播放
注:音频、视频解码器是C代码写的,所以MediaPlayer内部是通过JNI调用系统的C解码代码
a、MediaPlayer的生命周期的几种状态:
idle:当一个MediaPlayer对象被刚刚new出来或是调用了reset()方法后到达idle状态
initialized:初始化完成状态。执行setDataSource()方法后到达initialized状态
prepared:准备完成状态。执行同步准备prepare()或者异步准备prepareAsync()方法后到达prepared状态
注意prepare()是阻塞式方法,所以播放网络视频开发中都用prepareAsync()方法。prepareAsync()有回调函数
started:开始播放状态。执行start()或者seekTo()方法后到达started状态
paused:暂停播放状态。执行pause()方法后到达paused状态
stopped:停止播放状态。执行stop()方法后到达stopped状态
playbackComp:播放完成状态。
end:调用了release()方法后到达end状态
error:播放控制操作可能会失败,如不支持的音频/视频格式,缺少隔行扫描的音频/视频,分辨率太高,流超时等原因
一旦发生错误,MediaPlayer对象会进入到Error状态
MediaPlayer的两种创建方式:
****MediaPlayer mp = new MediaPlayer(); //此种方法创建必须调用prepare()或者prepareAsync()才能start()
****MediaPlayer.create(Context context,int resId); //此种方法系统neibu已经执行prepare()了,故可直接start()
b、MediaPlayer的监听事件
setOnCompletionListener(MediaPlayer.OnCompletionListener listener) 网络流媒体播放结束监听器
setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener listener) 网络流媒体的缓冲监听器
setOnErrorListener(MediaPlayer.OnErrorListener listener) 错误信息监听器
setOnVideoSizeChangedListener(MediaPlayer.OnVideoSizeChangedListener listener) 视频尺寸监听 器
setScreenOnWhilePlaying(boolean screenOn) 设置是否使用SurfaceHolder显示监听器
c、MediaPlayer的作用
****MediaPlayer通常和Service结合播放音频文件
****MediaPlayer通常和SurfaceView结合播放视频文件
播放应用的资源文件
播放应用的原始资源文件
播放外部存储器上的资源文件
播放网络资源文件
d、MediaPlayer的缺点
资源占用量较高,延迟时间较长
不支持多个音频同时播放
e、使用SoundPool播放音效
SoundPool使用音效池的概念来管理多个短促的音效。SoundPool主要用于播放密集、短促的音效。
SoundPool与MediaPlayer相比的优势是在于CPU资源占用量低和反应延迟下,另外SoundPool还支持自行设置声音的品质、音量、播放比率等参数
f、使用VideoView和MediaController播放视频
VideoView的概述:
VideoView的作用是显示和播放视频
VideoView封装了MediaPlayer,同时继承了SurfaceView
VideoView可以播放网络音频、视频文件,通常不支持rmvb格式的视频
使用VideoView播放视频的步骤:
创建VideoView组件
调用VideoView的setVideoPath(String path)或者setVideoURI(Uri uri)加载指定视频
调用VideoView的start()、stop()、pause()方法控制视频的播放
g、使用MediaPlayer和SurfaceView播放视频
②MediaRecorder:
手机一般都提供了麦克风硬件,而Android系统就可以利用该硬件来录制音频或者视频
③多媒体常识:
a、什么是多媒体
多媒体是计算机和视频技术的结合,实际上它是两个媒体;声音和图像,或者用现在的术语:音响和电视
b、常用的视频格式
Android系统默认:mp4、3gp
常用格式:ts、3gpp、3g2、3gpp2、avi、mkv、flv、divx、f4v、rm、rmvb、rv、wmv、asf、mov、mpg、v8、ram、mpeg、
swf、m2v、asx、ra、ram、ndivx、xvid等
c、常用音频格式:
Android系统:mp3、ogg;
常用格式:wma、mid、m4a、xmf、aac、mpa、midi、ar等
d、常用图片格式:PNG、GIF、BMP、jpg
e、android的多媒体应用:
视频播放器
音频播放器
相机
图片浏览器
视频通话
MediaScanner:开机或者SDcard插入时到系统库中扫描图片、音频和视频多媒体文件
f、MediaPlayer如何封装软解码:
在MediaPlayer类里面有一个静态代码块,该静态代码块完成调用用C语言编写的解码代码。
g、国内各个视频网站采用的解码框架:
优酷、搜狐、奇艺、pps、暴风影音土豆、56网都是用的ffmpeg
pptv已经使用p2p技术
点对点技术(peer-to-peer, 简称P2P)又称对等互联网络技术,是一种网络新技术,依赖网络中参与者的计算能力和带宽,
而不是把依赖都聚集在较少的几台服务器上。P2P网络通常用于通过Ad Hoc连接来连接节点。这类网络可以用于多种用途,
各种档案分享软件已经得到了广泛的使用。P2P技术也被使用在类似VoIP等实时媒体业务的数据通信中。
h、当播放过程出错处理机制:
提示用户播放错误
重新播放
使用第三方播放器
④能实现万能播放的框架:
概述:
虽然Android已经内置了VideoView组件和MediaPlayer类来支持开发视频播放器,但系统支持的格式、性能等各方面都十分有限
所以我们可以利用开源项目VLC、ffmpeg或者Vitamio来打造属于自己的Android万能播放器。
a、VLC框架:
VLC是一个开源项目,基于ffmpeg框架的自定义播放器。其中LibVLC是VLC的核心部分,就相当于MediaPlayer类
VLC一个最主要的部分,它可以播放各种类型的媒体文件和流媒体文件,并且可以创造媒体流并保存成各种格式的媒体文件
VLC是一种跨平台的媒体播放器和流媒体服务器,最初为videolan的客户端,它是一种非常简便的多媒体播放器,
它可以用来播放各种各样的音视频的格式文件(MPEG-1、MPEG-2、MPEG- 4、DivX、WMV、mp3、OGG、Vorbis、AC3、AAC等等)流媒体协议
最具特色的功能是可以边下载边观看Divx媒体文件,并可以播放不完全的AVI文件。并且支持界面的更改。
缺点:有C/C++代码,还有Java代码,代码太庞大
b、ffmpeg框架:
优点:轻量级框架,易于维护
FFmpeg是一个集录制、转换、音/视频编码解码功能为一体的完整的开源解决方案
FFMPEG几乎为你把所有的繁重工作都做了,比如解码、编码、复用和解复用。
这使得多媒体应用程序变得容易编写。它是一个简单的,用C编写的,快速的并且能够解码
几乎所有你能用到的格式,当然也包括编码多种格式。
FFmpeg支持MPEG、DivX、MPEG4、AC3、DV、FLV等40多种编码,支持AVI、MPEG、OGG、Matroska、ASF等90多种解码
FFmpeg主目录下主要有libavcodec、libavformat和libavutil等子目录。其中libavcodec用于存放各个encode/decode模块
libavformat用于存放muxer/demuxer模块,libavutil用于存放内存操作等辅助性模块
c、vitamio框架:
vitamio也是基于ffmpeg开源框架
VPlayer是vitamio的一个产品,vitamio和VPlayer是同一个团队开发的,VPlayer能播放的vitamio也能播放
vitamio的成功案例:
国内:VPlayer、熊猫影音、321影音等
国外:Tvltaliane、Dizi TV等
vitamio支持的网络协议:
m3u8
MMS
RTSP (RTP, SDP)
HTTP流式传输(progressive streaming)
HTTP Live Streaming (M3U8), Android 2.1+
vitamio的组成:
vitamio.jar
ARMv-7-NEON.apk
四个解码器:
ARMv-7-NEON.apk
VFP.apk
ARMv6.apk
ARMv5.apk
注:vitamio根据手机CPU型号安装对应的解码器,只安装一个解码器。
vitamio不是万能的,因为手机上的Android系统都被手机厂商改过,所以vitamio不支持所有的手机,但是支持大部分的手机。
解码:
硬解码:用系统接口实现的播放器。
软解码:不用系统接口实现的播放器。
注:系统播放器是硬解码。硬解码视频质量比软解码质量好,系统播放器的播放质量肯定比第三方播放器的播放质量好。
d、流媒体:
VLS:是一种流服务器,专门用来解决流的各种问题,它也具有一些VLC的特征。videolan作为服务器可以输出http,rtp,rtsp的流。
流媒体概述:
所谓流媒体是指采用流式传输的方式在Internet播放的媒体格式。
流媒体又叫流式媒体,它是指商家用一个视频传送服务器把节目当成数据包发出,传送到网络上。
用户通过解压设备对这些数据进行解压后,节目就会像发送前那样显示出来。
流媒体以流的方式在网络中传输音频、视频和多媒体文件的形式。
流媒体文件格式是支持采用流式传输及播放的媒体格式。
流式传输方式是将视频和音频等多媒体文件经过特殊的压缩方式分成一个个压缩包,
由服务器向用户计算机连续、实时传送。在采用流式传输方式的系统中,用户不必像非流式播放那样等到整个文件
全部下载完毕后才能看到当中的内容,而是只需要经过几秒钟或几十秒的启动延时即可在用户计算机上利用
相应的播放器对压缩的视频或音频等流式媒体文件进行播放,剩余的部分将继续进行下载,直至播放完毕。
⑤如何实现视频的高质量播放:
高清、加载快、拖动快、没有广告
(6)AsyncTask和AsyncQueryHandler框架
1)AsyncTask:
①AsyncTask概述:
AsyncTask是Android 1.5提供的一个轻量级的异步任务工具,是一个封装好的后台任务类。
②AsyncTask使用原则:
a、AsyncTask实例必须在主界面线程中创建
b、execute方法必须在主界面线程中执行
c、不要手动的调用onPreExecute、doInBackground、onPostExecute和onProgressUpdate方法
d、多次调用将会出现异常
③AsyncTask和Handler的异同点:
a、相同点:
AsyncTask和Handler都能通过主线程和子线程之间的通信更新主界面
b、不同点:
Handler比较麻烦,而AsyncTask使任务更加方便,而且AsyncTask过程可控。
对于多个后台任务时,使用Handler代码结构清晰简单;而使用多个AsyncTask时容易发生异常
2)AsyncQueryHandler:
①AsyncQueryHandler概述:
a、AsyncQueryHandler继承于Handler
②AsyncQueryHandler的作用:
对ContentProvider提供的数据进行增删改查。
③AsyncQueryHandler的工作机制:
注:AsyncQueryHandler内部需要Handler、Looper、Message、HandlerThread、WorkerHandler和WorkerArgs配合使用完成异步任务
a、创建AsyncQueryHandler对象时,会调用系统的AsyncQueryHandler构造方法,在AsyncQueryHandler构造方法里,
系统会进行如下操作:
创建并开启一个HandlerThread、同时初始化Looper对象和Handler对象
b、当调用AsyncQueryHandler的startQuery、startInsert、startUpdate或者startDelete方法时
就会执行相应的增删改查方法,在AsyncQueryHandler的增删改查方法里面先通过Handler对象初始化Message对象,
然后再初始化一个WorkerArgs对象,将任务参数信息封装到WorkerArgs对象中,
最后再通过Handler对象的sengMessage方法将异步任务的消息发送出去
c、WorkerHandler收到消息后调用其handleMessage方法,在该方法里对异步任务的操作类型进行判断,然后执行与之对应的处理
d、最后回调指定的异步任务执行完成的回调方法,该回调方法系统是空实现,需要用户自己根据自己的业务去重写
④AsyncQueryHandler的使用注意事项:
大数据时会出现ANR异常,故需要优化。
(7)常用设计模式和算法:
(1)常用设计模式:
注:什么叫设计模式?
解决某类问题行之有效的方法,是一种思想,是规律的总结
1)单例设计模式:
①概念:
保证一个类在内存中只有唯一一个对象。
②实现单例设计模式的步骤:
a、将构造函数私有化。构造函数私有化可避免其他程序创建该类对象
b、在本类中创建一个私有的该类对象
c、对外提供一个公共访问方式,为了方便其他程序访问到该类对象
③单例设计模式的两种方式:
a、饿汉式:
类一加载就创建对象
class Student
{
private Student(){}
private static final Student s = new Student();
public static Student getInstance()
{
return s;
}
}
b、饱汉式:
使用时才创建该对象
class Student
{
private Student(){}
private static final Student s = null;
public static Student getInstance()
{
if(s==null)
{
//线程1就进来了,线程2就进来了。
s = new Student();
}
return s;
}
}
c、饿汉式和饱汉式的区别:
****饿汉式是类一加载进内存就创建好了对象;而懒汉式则是类加载进内存的时候,对象还没有存在,要使用该对象的时候再new出来
****懒汉式是延迟加载,如果多个线程同时操作懒汉式时就有可能出现线程安全问题
为解决饱汉式的线程安全问题,解决线程安全问题可以加同步来解决。
但是加了同步之后,每一次都要比较锁,效率就变慢了,可以通过双重判断来提高程序效率。
注:开发常用饿汉式,因为饿汉式简单安全。懒汉式多线程的时候容易发生问题
④单例设计模式的应用:
当需要保证某个类在内存中有且仅有一个实例对象时,就用单例设计模式。比如java的Runtime类、Class类都是采用的单例设计模式
2)工厂模式:
①作用和好处:
作用:
提供创建对象的接口
好处:
a、隐藏创建细节
b、需要创建新对象时直接在配置文件修改就行,方便灵活
②工厂模式的分类:
a、简单工厂模式:
不利于产生系列产品
b、工厂方法模式:
多形性工厂
c、抽象工厂模式:
又称为工具箱,产生产品族,但不利于产生新的产品
③工厂模式的应用:
如XML文件的几种解析方法如DOM、SAX、PULL在创建解析器时都是用的工厂模式
④缺点:
缺点是当产品修改时,工厂类也要做相应的修改。
3)模板模式:
①概念:
定义一个操作中算法的骨架,将一些步骤的执行交给子类去完成。
在定义功能时,功能的一部分是确定的,有一部分是不确定的,而且确定的部分在使用不确定的部分,
可将不确定的部分暴露出去,由该类的子类去完成。
②模板设计模式的应用:
a、Servlet就是用的模板设计模式
b、如Android开发中的BaseActivity。几乎每个Activity都要执行findview、setview、监听事件和处理事件等操作。
故我们可以将这些共同的操作抽取出来形成一个模板。
c、模板设计模式在一些开源框架中应用很多
4)代理模式:
①定义:
为其他对象提供一种代理以控制对这个对象的访问
②代理模式的应用场景:
a、授权机制
b、不能直接访问对象,但又必须和这个对象进行交互
③代理模式如何用?
比如我要找李宇春唱歌,李宇春很忙,我只能找她经纪人,经纪人虽然不会唱歌,但是通过经纪人这个中间人可以调用李宇春唱歌。
5)策略模式:
①定义:
策略模式就是用来封装算法的。
策略模式定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
②概述:
策略模式把行为和环境分开。环境类负责维持和查询行为类,各种算法在具体的策略类中提供。
由于算法和环境独立开来,算法的增减,修改都不会影响到环境和客户端。
③策略模式的应用场景:
策略模式是用来封装算法的。
只要在不同时间应用不同的业务规则,就可以考虑用策略模式处理这种变化的可能性。
6)装饰模式:
①概念:
装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,提供比继承更多的灵活性。
动态给一个对象增加功能,这些功能可以再动态的撤消。增加由一些基本功能的排列组合而产生的非常大量的功能。
7)适配器模式:
①概念:
将一个类的接口转换成客户希望的另外一个接口。适配器模式使原本由于接口不兼容而不能一起工作的那些类可以一起工作。
②应用场景:
两个类所做的事情相同或者相似,但是具有不同的接口时就可以考虑适配器模式。
8)观察者模式:
①概念:
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某个主题对象。
这个主题对象在状态发生变化时,会通知所有的观察者,使他们能够自己更新自己。
适配类可以根据参数返还一个合适的实例给客户端。
②概述:
所谓知己知彼百战不殆。
(8)手机定位、地图:
1)Android手机定位的三种方式:
①基站定位:
根据手机基带和附近的基站,通过手机信号的强弱来定位手机。
但是这种定位方式的精确度跟手机离基站的远近以及手机附近基站的密集程度有关系。
精度为20米-2000米不等。
②wifi定位(也叫网络定位):
当手机连接网络的时候,会动态获取一个ip地址,运营商会让ip跟实际位置有一个一一对应关系,所以通过ip地址也可以定位手机。
比如Google公司的谷歌纵横。
因为手机获取到的ip都是运营商根据手机所处位置动态分配的ip,所以这种方式进行手机定位的精确度比较差,精确度为200米+
③GPS定位:
手机都会自带一个比较便宜的非专业的A-GPS模块,通过免费的光波的方式和卫星进行通信。
因为是通过光波的方式,所以就要求头顶必须空旷。
像汽车上比较专业的GPS设备,会进行信号一些放大和增益,进行手机定位也就比较不受限制和精确。
精确度跟GPS模块的精度有关,通常为2米-10米。
2)Google Map:
①获取Google Map API的Key:
为了在应用程序中调用Google Map,必须先获取Google Map API的Key。
②安装Google Map API插件:
Android SDK默认并不支持Google Map,为了得到支持Google Map的SDK,必须为Android SDK增加相应的插件:AVD。
③创建支持Google Map API的虚拟设备:
为Android SDK安装Google Map API插件后,还需要创建一个支持Google Map API的虚拟设备。
④Google Map API:
a、MapView:
为了在Android平台上调用Google Map服务,Google Map提供了一个MapView,
这个MapView的用法就像普通的ImageView一样,直接在界面布局文件中定义它,然后在程序中控制该组件即可。
b、MapController:
通过MapView.getController()可获取MapController对象
MapController可对MapView进行控制,比如控制地图定位到指定位置或者地图放大、缩小等
c、Overlay:
通过MapView.getOverlay()可获取Overlay对象
Overlay是附加在Google Map上的附加图片,应用可以控制向Google Map上添加任意多个Overlay
d、GeoPoint:
GeoPoint类表示Google Map上的指定点
GeoPoint就是对经度和纬度的封装
⑤使用Google Map API定位的步骤:
a、获取MapView对应的MapController对象
b、根据经度、纬度值创建GeoPoint对象
c、调用MapView控件所关联的MapController对象的animateTo(GeoPoint point)方法定位到指定位置
注意:
在布局文件中引入MapView要通过包名.类名的方式
在布局文件中定义MapView必须要设置android:apiKey,其值为①中申请到的Key
⑥GPS导航:
把GPS导航和Google Map结合起来使用,可以非常方便的开发出GPS导航应用
a、通过Context.getSystemService(Context.LOCATION_SERVICE)方法获取LocationManager对象
b、通过LocationManager对象每隔一段时间获取GPS定位信息
c、根据LocationManager对象每隔一段时间获取的GPS定位信息,通过MapView将地图定位到指定位置
⑦根据地址定位:
Google Map必须通过经度和纬度来进行定位,而普通用户不可能记住某个位置的经度和纬度,
所以对普通用户来说根据地址定位才是有价值的地图应用
为此,需要进行如下两个操作:
a、地址解析:
把字符串地址转换为经、纬度
b、反向地址解析:
把经、纬度转换为字符串地址
Android为地址解析提供了Geocoder工具类,该工具类提供如下两个方法进行地址解析和反向地址解析
a、List<Address> getFromLocation(double latitude, double longtitude, int maxResults)
执行地址解析,把经、纬度值转换为字符串地址
b、List<Address> getFromLocationName(String locationName, int maxResults)
执行反向地址解析,将字符串地址转换为经、纬度值
3)火星坐标系统:
①现在绝大多数的GPS获取到的经度和纬度都是美国的卫星,我们国内也有北斗卫星,但是至今没给民用。
通过美国卫星获取到的经、纬度是国际标准的经、纬度;
而国际标准的经纬度在中国地图上显示的位置是不准确的;
为了拿国际标准的经纬度在中国地图上获取到准确的位置,需要把国际标准的经纬度转换成中国的火星坐标
才能获取到准确的位置