(1):Android的体系结构html
Application(应用程序) Application framework(应用程序框架) Libraries(库) Android Runtime(运行时,包括核心库和虚拟机) linux kernel(linux内核)linux
(2):Android的四大组件android
Activity service contentprovider(内容提供者) broadcastReceiver(广播器)数据库
(3): Android中四大组件的生命周期编程
(1)设置 android:configChanges="orientation" 和不设置这个属性,这两个效果是同样的,activity都是从新创新安全
(2)横屏切竖屏,以及竖屏切回横屏,这两个也是同样的(以下总结),不会出现网上说的横屏切回竖屏时,生命周期执行两遍的问题服务器
1)从新建立activity的生命周期网络
a)2.3上:onSaveInstanceState->onPause->onStop->onCreate->onStart->onRestoreInstanceState->onResume架构
b)4.0上(3.2我没测试,只测试了4.0的):onPause->onSaveInstanceState->onStop->onCreate->onStart->onRestoreInstanceState->onResumeapp
2)不从新建立activity,只会调用 onConfigurationChanged
(3)targetSdkVersion会影响生命周期,targetSdkVersion在12及如下的话,设置了 android:configChanges="orientation|keyboardHidden" ,在机器上都不会从新建立activity,只会调用 onConfigurationChanged,若是设置targetSdkVersion>12的话,只在sdkVersion<=12的机器上有效果,>12的机器上activity仍是会从新建立(须要加上screenSize才有效果)
(4)android2.3和android4.0的生命周期不同,2.3是先onSaveInstanceState,后onPause,4.0是先onPause,后onSaveInstanceState(这个我表示不想吐槽了)
a)建立ServerSocket的方法:
ServerSocket(Int localPort)
ServerSocket(int localport,int queueLimit)
ServerSocket(int localport,int queueLimit,InetAddress localAddr)
建立一个ServerSocket必须指定一个端口,以便客户端可以向该端口号发送链接请求。端口的有效范围是0-65535 (0-1023是系统预留的,最好大于1024)
0~1023的端口号为系统所保留,例如http服务的端口号是80,telnet服务的端口号为21,ftp为23。因此咱们在选择端口号时最好选择大于1023的数,防止发生冲突。在建立Socket时,若是发生错误,将产生IOException,在程序中必须对其进行处理。因此在建立Socket或ServerSocket时必须捕获或抛出异常。
b)ServerSocket操做
1,Socket accept()
accept()方法为下一个传入的链接请求建立Socket实例,并将已成功链接的Socket实例返回给服务器套接字,若是没有链接请求,accept()方法将阻塞等待;
2,void close
close方法用于关闭套接字
2,Socket
a)建立Socket的方法:
Socket(InetAddress remoteAddress,int remotePort)
利用Socket构造函数,可建立一个TCP套接字后,先链接到指定的远程地址和端口号。
Socket(InetAddress address,int port ,InetAddress localAddr ,int localPort)
Socket(InetAddress address, int port ,boolean stream)
Socket(SocketImpl impl)
address、host、port分别表示双向链接中另外一方的IP地址、主机名、端口号
stream指明Socket是流Socket仍是数据报Socket
localAddr,bindAddr是本地机器的地址(ServerSocket的主机地址)
impl是Socket的父类,既能够建立ServerSocket,也可建立Socket
b)操做Socket的方法
通讯过程当中顺序:服务器端首先获得输入流,而后将输入流信息输出到其各个客户端
Socket提供了getInputStream()和getOutputStream()方法来获得输入输出流。而后再对输入流输出流进行读写操做,例如,对于服务器端,获得Socket对象后,调用 getInputStream方法便可获得来自客户端的流,调用getOutStream方法可获得向客户端发送数据的流。对于客户端,调用getInputStream方法便可获得来自服务器的流,调用getOutStream方法可获得向服务器端发送数据的流。
InputStream getInputStream()
OutputStream getOutputStream()
可调用Socket的close()方法进行关闭,在关闭前,应将与Socket相关的全部输入输出流关闭,正着打开,倒着关闭。
编程步骤:
建立服务器的步骤:
1, 指定端口实例化一个ServerSocket
2, 调用ServerSocket的accept方法以在等待链接期间形成阻塞
3, 获取位于该底层Socket的流以进行读写操做
4, 将数据封装成流
5, 对Socket进行读写
6, 关闭打开的流
建立客户端的步骤:
1, 经过IP地址和端口实例化Socket,请求链接服务器
2, 获取Socket上的流以进行读写
3, 把流包装进BufferedReader/PrintWriter的实例
4, 对Socket进行读写
5, 关闭打开的流
当要监控多个客户端时,可以使用类ExecutorService
其对象获取方法:Executors.newCachedThreadPool();
调用该对象的execute(Runnable command)便可,在将来某个时间执行给定的命令。该命令可能在新的线程、已入池的线程或者正调用的线程中执行,这由 Executor 实现决定
三,使用基于UDP的Socket
a)建立DatagramSocket
DatagramSocket(byte [] data,int offset,int length,InetAddress remoteAddr,int remotePort)
该构造函数建立一个数据报文对象,数据包含在第一个参数data当中
Offset是指偏移量长度,length是指数据包长度。
b)建立DatagramSocket
DatagramSocket(int localPort)
以上构造函数将建立一个UDP套接字;
c)DatagramSocket:发送和接受
void send(DatagramPacket packet)
void receive(DatagramPacket packet)
send()方法用来发送DatagramPacket实例。一旦建立链接,数据报将发送到该套接字所链接的地址;
receive()方法将阻塞等待,知道接收到数据报文,并将报文中的数据复制到指定的DatagramPacket实例中。
补充:
对AndroidManifest.xml的配置必定不要忘了:
<uses-permission android:name="android.permission.INTERNET"/>
输入和输出流要用DataOutputStream和DataOutputStream,不能够用PrintWriter、StreamReader等。
适用范围:保存少许的数据,且这些数据的格式很是简单:字符串型、基本类型的值。好比应用程序的各类配置信息(如是否打开音效、是否使用震动效果、小游戏的玩家积分等),解锁口 令密码等
核心原理:保存基于XML文件存储的key-value键值对数据,一般用来存储一些简单的配置信息。经过DDMS的File Explorer面板,展开文件浏览树,很明显SharedPreferences数据老是存储在/data/data/<package name>/shared_prefs目录下。SharedPreferences对象自己只能获取数据而不支持存储和修改,存储修改是经过SharedPreferences.edit()获取的内部接口Editor对象实现。 SharedPreferences自己是一 个接口,程序没法直接建立SharedPreferences实例,只能经过Context提供的getSharedPreferences(String name, int mode)方法来获取SharedPreferences实例,该方法中name表示要操做的xml文件名,第二个参数具体以下:
Context.MODE_PRIVATE: 指定该SharedPreferences数据只能被本应用程序读、写。
Context.MODE_WORLD_READABLE: 指定该SharedPreferences数据能被其余应用程序读,但不能写。
Context.MODE_WORLD_WRITEABLE: 指定该SharedPreferences数据能被其余应用程序读,写
Editor有以下主要重要方法:
SharedPreferences.Editor clear():清空SharedPreferences里全部数据
SharedPreferences.Editor putXxx(String key , xxx value): 向SharedPreferences存入指定key对应的数据,其中xxx 能够是boolean,float,int等各类基本类型据
SharedPreferences.Editor remove(): 删除SharedPreferences中指定key对应的数据项
boolean commit(): 当Editor编辑完成后,使用该方法提交修改
读写其余应用的SharedPreferences: 步骤以下
一、在建立SharedPreferences时,指定MODE_WORLD_READABLE模式,代表该SharedPreferences数据能够被其余程序读取
二、建立其余应用程序对应的Context:
Context pvCount = createPackageContext("com.tony.app", Context.CONTEXT_IGNORE_SECURITY);这里的com.tony.app就是其余程序的包名
三、使用其余程序的Context获取对应的SharedPreferences
SharedPreferences read = pvCount.getSharedPreferences("lock", Context.MODE_WORLD_READABLE);
四、若是是写入数据,使用Editor接口便可,全部其余操做均和前面一致。
核心原理: Context提供了两个方法来打开数据文件里的文件IO流 FileInputStream openFileInput(String name); FileOutputStream(String name , int mode),这两个方法第一个参数 用于指定文件名,第二个参数指定打开文件的模式。具体有如下值可选:
MODE_PRIVATE:为默认操做模式,表明该文件是私有数据,只能被应用自己访问,在该模式下,写入的内容会覆盖原文件的内容,若是想把新写入的内容追加到原文件中。可 以使用Context.MODE_APPEND
MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,不然就建立新文件。
MODE_WORLD_READABLE:表示当前文件能够被其余应用读取;
MODE_WORLD_WRITEABLE:表示当前文件能够被其余应用写入。
除此以外,Context还提供了以下几个重要的方法:
getDir(String name , int mode):在应用程序的数据文件夹下获取或者建立name对应的子目录
File getFilesDir():获取该应用程序的数据文件夹得绝对路径
String[] fileList():返回该应用数据文件夹的所有文件
读写sdcard上的文件
其中读写步骤按以下进行:
一、调用Environment的getExternalStorageState()方法判断手机上是否插了sd卡,且应用程序具备读写SD卡的权限,以下代码将返回true
Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
二、调用Environment.getExternalStorageDirectory()方法来获取外部存储器,也就是SD卡的目录,或者使用"/mnt/sdcard/"目录
三、使用IO流操做SD卡上的文件
注意点:手机应该已插入SD卡,对于模拟器而言,可经过mksdcard命令来建立虚拟存储卡
必须在AndroidManifest.xml上配置读写SD卡的权限
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
SQLite是轻量级嵌入式数据库引擎,它支持 SQL 语言,而且只利用不多的内存就有很好的性能。如今的主流移动设备像Android、iPhone等都使用SQLite做为复杂数据的存储引擎,在咱们为移动设备开发应用程序时,也许就要使用到SQLite来存储咱们大量的数据,因此咱们就须要掌握移动设备上的SQLite开发技巧
Android系统中能实现全部应用程序共享的一种数据存储方式,因为数据一般在各应用间的是互相私密的,因此此存储方式较少使用,可是其又是必不可少的一种存储方式。例如音频,视频,图片和通信录,通常均可以采用此种方式进行存储。每一个Content Provider都会对外提供一个公共的URI(包装成Uri对象),若是应用程序有数据须要共享时,就须要使用Content Provider为这些数据定义一个URI,而后其余的应用程序就经过Content Provider传入这个URI来对数据进行操做。
在Android的UI开发中,咱们常常会使用Handler来控制主UI程序的界面变化。有关Handler的做用,咱们总结为:与其余线程协同工做,接收其余线程的消息并经过接收到的消息更新主UI线程的内容。
咱们假设在一个UI界面上面,有一个按钮,当点击这个按钮的时候,会进行网络链接,并把网络上的一个字符串拿下来显示到界面上的一个 TextView上面,这时就出现了一个问题,若是这个网络链接的延迟过大,多是10秒钟甚至更长,那咱们的界面将处于一直假死状态,而若是这段时间超 过5秒钟的话,程序会出现异常。
这时咱们会想到使用线程来完成以上工做,即当按钮被按下的时候新开启一个线程来完成网络链接工做,并把获得的结果更新到UI上面。可是,这时候又会 出现另外一个问题,在Android中,主线程是非线程安全的,也就是说UI的更新只能在本线程中完成,其余线程没法直接对主线程进行操做。
为了解决以上问题,Android设计了Handler机制,由Handler来负责与子线程进行通信,从而让子线程与主线程之间创建起协做的桥梁,使Android的UI更新的问题获得完美的解决。
Handler的工做原理
通常状况下,在主线程中咱们绑定了Handler,并在事件触发上面建立新的线程用于完成某些耗时的操做,当子线程中的工做完成以后,会对Handler发送一个完成的信号,而Handler接收到信号后,就进行主UI界面的更新操做。
andriod提供了 Handler 和 Looper 来知足线程间的通讯。
Handler 先进先出原则。
Looper类用来管理特定线程内对象之间的消息交换(Message Exchang搜索e)。
1)Looper: 一个线程能够产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。
2)Handler: 你能够构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper从Message Queue取出)所送来的消息。
3) Message Queue(消息队列):用来存放线程放入的消息。
4)线程:UI thread 一般就是main thread,而Android启动程序时会替它创建一个Message Queue。
Android程序启动后会起一个进程,全部的组件都在这个进程里面运行。开始这个进程只包含一个线程(备注进程怎么能包含线程,我认为说法有误),叫作UI主线程,负责处理UI界面的显示更新。对于一些费时的操做(超过5S会卡顿)须要单独启动一个子线程去处理。子线程处理完毕将结果通知给UI主线程,主线程获得结果后更新UI界面。子线程与UI主线程的通讯在android中使用了消息机制来完成,那么是怎么完成的呢?这就和handler 机制的原理,简而言之言而总之,就是须要两样样古老的东西,消息队列、轮询。也就是说,主线程起来之后有一个消息队列,同时和该队列配对的有一个轮询,而子线程有这个消息队列的引用,那这样,子线程处理完之后就会向主线程的消息队列发消息,主线程轮询本身的队列,发现有未处理的消息就进行处理。
在电脑术语中,统一资源标识符(Uniform Resource Identifier,或URI)是一个用于标识某一互联网资源名称的字符串。 该种标识容许用户对任何(包括本地和互联网)的资源经过特定的协议进行交互操做。URI由包括肯定语法和相关协议的方案所定义。