零碎小知识点复习
Java/Android 基础知识回顾
年纪大了,越来越多的东西记不住,为了便于复习,将零零碎碎的知识点回顾下,想到什么写什么吧。
1.设置activity为窗体样式
<activity android:theme="@android:style/Theme.Dialog"></activity>
2.在activity被系统回收时,如果需要保存当前状态,可以重写activity的onSaveInstanceState方法,在此方法中做相应的数据处理操作,比如将sessionid存储在Bundle对象中(键值对的形式)。
@Override
protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putLong("sessionid", 123); }
下次activity被创建时,则在activity的onCreate方法中中恢复数据,也可在onRestoreInstanceState方法中取出数据
@Override
public void onCreate(Bundle savedInstanceState) { if(savedInstanceState!=null){ long myLong = saveInstanceState.getLong("sessionid"); } super.onCreate(savedInstanceState); }
@Override public void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); // Restore UI state from the savedInstanceState. // This bundle has also been passed to onCreate. long myLong = savedInstanceState.getLong("sessionid"); }
http://stackoverflow.com/questions/151777/saving-activity-state-in-android
3.进制转换
Java中常量分为:整数常量,小数常量,布尔型常量,字符常量,字符串常量,null常量。其中对于整数常量有三种表现形式:二进制,八进制(0),十进制,十六进制(0x)。
①十进制转二进制:对十进制做除2运算,得到的余数逆序排列,即是对应的二进制。
②二进制转十进制:对二进制做乘2运算,二进制中对应为1的位置依据规律(128 64 32 16 8 4 2 1)相加,得到的数,即是对应的十进制。
③二进制 <-> 八进制 & 二进制 <-> 十六进制 互转:3位二进制对应1位八进制,4位二进制对应1位十六进制。
④其他进制互转:以二进制为中间桥梁,如十进制转十六进制,可以先将十进制转换成二进制,再将二进制转换成十六进制,即以上①③步骤的组合。
当然类似于十进制转二进制,也可以直接对十进制做除16运算,得到余数逆序排列,即是对应的十六进制。(所做除法过于复杂,不推荐)
⑤负数的二进制:对应的正数二进制取反加1。
4.数据类型
|---基本数据类型
|---数值型
|---整数类型:byte(1位)、short(2)、int(4)、long(8) 默认类型:int
|---浮点类型:folat(4)、double(8) 默认类型:double
|---字符型:char(2) 字符类型内部是字符的Unicode(国际码表)代码,有65535个不同字符
|---布尔型:boolean
八大基本数据类型:四种是整数类型(整型),两种浮点类型,一种字符型,一种用于表示真假的浮点型。
|---引用数据类型
|---类:class(较为特殊且常用:String字符串类)
|---接口:interface
|---数组:[]
5.除法 & 取模 & 转义字符
public class Test { /** * 除法&取模&转义字符 复习 */ public static void main(String[] args) { int x = 4329; x = x / 1000 * 1000; System.out.println(x);// 4000 // 左边小于右边,结果等于左边 System.out.println(1 % 5);// 1 System.out.println(3 % 5);// 3 // 右边为1,结果始终未0 System.out.println(5 % 1);// 0 // 负数与否看左边(被模数),左边有负号结果就为负 System.out.println(-1 % 5);// -1 System.out.println(1 % -5);// 1 /* * 转义字符:通过\ 来转变后面字母或符号的含义 * \n:换行 * \t:制表符(tab键) * \b:退格(backspace键) * \r:回车 * linux中换行由一个字符表示:\n, windows中换行由两个字符表示:\r\n, dos下直接能识别:\n */ System.out.println("a\nb"); System.out.println("\"java\"");// "java" System.out.println("\\java\\");// \java\ } }
6.数据封装在对象中,对象则封装在集合中,其实总的来说,对象的存储方式有两种:数组和集合,两者区别:
①数组长度固定,集合长度可变。
②数组只能存储一种数据类型,数组存储的类型在声明时已经明确,集合能同时存储多种数据类型。
③数组可存储基本数据类型,集合则不能,集合只能存储对象,但是可以先将基本数据类型用基本数据类型对象包装类进行封装,而后再存储在集合中。
7.集合
①集合中存储的都是对象的引用,即:地址
8.Android程序的入口
android.app.Application下的onCreate()方法
9.& | ^
①6 & 3 = 2 (都为真才是真) 110 & 011 ------- 010 ②6 | 3 = 7 (有一个为真就是真) 110 | 011 ------- 111 ③6 ^ 3 = 5 (不同为真,相同为假,用于加密解密) 110 ^ 011 ------- 101
④^的技巧使用(对两个整数变量的值进行互换,不定以第三方变量,使用^作为中间量运算)
n = n ^ m;
m = n ^ m;
n = n ^ m;
9.5流程控制语句
计算机高级语言程序设计中有三种流程控制结构,分别是:顺序,分支和循环。
分支结构又有两种语句形式:if语句和switch语句。
循环结构有三种形式:for循环,while循环、do...while循环。
其中
①for循环的形式为:for (initialization; condition; increment) statement;
for 语句的循环控制的第一部分通常是对循环变量的初始化,第二部分给出进行循环需要满足的条件,第三部分则是对循环变量的更新。
②while循环的形式为:while (condition) statement;
while循环首先对循环条件进行判断,只有在循环条件满足的情况下才执行循环体。
③do…while循环的形式为:do statement while (condition);
与while循环不同的是,do…while循环首先执行一次循环体,当循环条件满足时则继续进行下一次循环。
10.三元运算符和if...else
两者的区别是,三元运算符可以简化if...else代码,但是因为它是一个运算符,所以运算完毕后必须要有一个结果,比如判断内只有一个输出语句是不能使用三元运算符的。
//正确 if(a>1){ System.out.println("a"); }else{ System.put.println("b"); } //错误 x = (a>1)?System.out.println("a"):System.out.println("b");
11.选择语句
if;if...else;是判断语句,做判断题。
switch是选择语句,做选择题。switch接受的数据类型:byte,short,int,char,String以及枚举。
12.循环语句while和do...while的区别
while是先判断while中的条件,条件符合,才执行循环体中的内容
do...while是先执行循环体中的内容,再判断while中的条件,条件符合才继续循环执行循环体中内容。
简单来说do...while先执行再判断,也就是桌do...while不论条件是否符合至少执行一次。
int x = 1; while(x<5){ System.out.println("x="+x); x++; } int y = 1; do{ System.out.println("y="+y); y++; } while(y<5);//注意书写格式--分号结束(语句结束要么是分号要么是大括号)
13.循环语句for和while的区别
如果变量只作为循环的增量而存在,而控制循环的次数,使用for循环内存较为优化。因为for循环中初始化的变量,作用域只在当前循环,当循环结束,变量在内存中被释放。
而while循环定义的变量,即使循环结束,依旧驻留在内存中。
简而言之,如果只为定义增量使用for。(当然while也可
14.for循环打印图形的简单规律
尖朝上,改变条件,让条件随着外循环变化。
尖朝下,改变初始化值,让初始化值随着外循环变化。
外循环控制行数,内循环控制每行打印的具体信息。
public class Test { /** * 打印九九乘法表 */ public static void main(String[] args) { printTimesTable(9); } public static void printTimesTable(int row) { for (int x = 1; x <= row; x++) { for (int y = 1; y <= x; y++) { if (y != x) { System.out.print(y + "*" + x + "=" + (y * x) + "\t"); } else { System.out.print(y + "*" + x + "=" + (y * x)); } } System.out.println(); } } } --> 1*1=1 1*2=2 2*2=4 1*3=3 2*3=6 3*3=9 1*4=4 2*4=8 3*4=12 4*4=16 1*5=5 2*5=10 3*5=15 4*5=20 5*5=25 1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36 1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49 1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64 1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
//打印三角形 public static void printTriangle(int row) { for (int x = 0; x < row; x++) { for (int y = x; y < row-1; y++) { System.out.print(" "); } for(int z = 0; z <= x; z++ ){ System.out.print("* "); } System.out.println(); } } --> * * * * * * * * * * * * * * *
//尖朝上 public static void printBase1(){ for (int x = 0; x < 5; x++) { for (int y = 0; y <= x; y++) { System.out.print("*"); } System.out.println(); } } //尖朝下 public static void printBase2(){ for (int x = 0; x < 5; x++) { for (int y = x; y < 5; y++) { System.out.print("*"); } System.out.println(); } } --> * ** *** **** ***** ------- ***** **** *** ** *
//正向镂空三角形 public static void printEmptyTriangle(int row) { for (int x = 0; x < row; x++) { for (int y = x + 1; y < row; y++) { System.out.print(" "); } for (int z = 0; z <= x; z++) { if (z == x) {// 一行中的最后一个点 System.out.print("*"); } else if (z == 0) {// 一行中的第一个点 System.out.print("* "); } else { if (x == row - 1) {// 最后一行 System.out.print("* "); } else { System.out.print(" "); } } } System.out.println(); } } --> row=5 * * * * * * * * * * * * //反向镂空三角形 public static void printEmptyTriangle2(int row) { for (int x = 0; x < row; x++) { for (int y = 1; y <= x; y++) { System.out.print(" "); } for (int z = x; z < row; z++) { if (z == row - 1) {// 一行中的最后一个点 System.out.print("*"); } else if (z == x) {// 一行中的第一个点 System.out.print("* "); } else { if (x == 0) {// 第一行 System.out.print("* "); } else { System.out.print(" "); } } } System.out.println(); } } --> row=5 * * * * * * * * * * * *
15.跳出循环
①break跳出当前循环
②通过定义标号,跳出指定循环
③与此类似continue也能定义标号跳出循环
a:for(int x = 0; x<3; x++){ b:for(int y =0; y<3; y++){ break a;//跳出a循环(如果只写break,则跳出b循环,即当前循环) } }
注意:
①break和continue单独存在时,他们之下不能有任何语句,因为都执行不到,相当于废话。
②注意break和continue的使用范围:break作用于switch或循环中,continue只用于循环中。
16.重载和重写
①重载/Overload:同名函数,参数列表(参数列表包括:参数个数,参数类型以及参数顺序)不同,和返回值无关。
当定义的功能相同,参与运算的未知内容不同的时候,这时候就使用到了函数的重载。
②重写/覆盖/Override
17.内存结构(栈内存,堆内存,方法区,本地方法区,寄存器)
①栈内存(Stack):局部变量(方法中的变量,方法参数中的变量,for循环中的变量)都在栈内存中。
栈内存中数据的特点:数据使用完毕,会自动释放。(for循环中初始化的变量就是在栈内存中,所以当循环结束,变量会自动释放。for和while的最大区别就在于此)
②堆内存(Heap):数组和对象(数组也称之为对象),通过new建立的实例/实体都存放在堆内存中。(实体是用于存储数据的)
堆内存中数据的特点:
a.堆内存中的实体数据都有一个地址值,栈内存中的变量通过地址值和堆内存中的实体数据建立对应关系。对象(类或是接口,直接或间接创建出来的对象)和数组也称之为引用数据类型,就是这么来的。
int[] arr = new int[3];System.out.println(arr);-->打印结果类似:[I@de2afb,此时打印的就是数组实体的引用/地址。
@左侧:"["表示数组,"I"表示Integer,即数组类型的引用存储的是int类型的数据。@右侧则是由哈希算法计算出来的哈希值,即数组实体存放的十六进制内存地址值。
b.堆内存中的实体是用于封装数据的,其中的数据都有默认初始化值(成员变量也存在于堆内存中),不同的数据类型对应不同的默认初始化值:int--0,double--0.0,float--0.0f,boolean--false,引用数据类型--null。
c.垃圾回收:当一个实体在堆内存中没有被任何引用使用时,会被JVM看做是垃圾而回收。[栈:自动释放;堆:垃圾回收]
d.堆内存空间在程序运行时才开辟。编译时只检查语法错误。所以类似:int[] arr = new int[3]; System.out.println(arr[3]);编译阶段是没有问题的,只有当程序运行时才报角标越界异常。
18.选择排序,冒泡排序,Java Api排序,普通查找,折半查找
// 选择排序(指定一个元素位置依次和其他元素比较)--尖朝下(改初始化值) public static void selectSort(int[] arr) { for (int x = 0; x < arr.length - 1; x++) { for (int y = x + 1; y < arr.length; y++) { if (arr[x] > arr[y]) { int temp = arr[x]; arr[x] = arr[y]; arr[y] = temp; } } } } // 冒泡排序(相邻元素比较)--尖朝上(改条件)--气泡往上冒 public static void bubbleSort(int[] arr) { for (int x = 0; x < arr.length - 1; x++) { for (int y = 0; y < arr.length - x - 1; y++) { if (arr[y] > arr[y + 1]) { int temp = arr[y]; arr[y] = arr[y + 1]; arr[y + 1] = temp; } } } } // 高效排序原理:在栈内存中进行数据的临时存储--记录需要置换的元素的角标,减少堆内存中元素的置换次数。 // java api排序 public static void javaApi(int[] arr) { Arrays.sort(arr); }
// 元素查找(普通方式,较低效) public static int getIndex(int[] arr, int key) { for (int i = 0; i < arr.length; i++) { if (key == arr[i]) { return i; } } return -1; } // 折半查找,折半的前提:数组是有序的 public static int halfSearch(int[] arr, int key) { int min = 0; int max = arr.length - 1; int mid = (min + max) / 2; // 循环条件是:只要没有找到元素就一直循环,直到最小值比最大值还大的时候跳出循环,并返回整数值-1,表示没有找到元素 while (key != arr[mid]) { if (key > arr[mid]) { min = mid + 1; } else if (key < arr[mid]) { max = mid - 1; } if (min > max) { return -1; } mid = (min + max) / 2; } return mid; } // 折半的第二种方式 public static int halfSearch2(int[] arr, int key) { int min = 0; int max = arr.length - 1; int mid = (min + max) / 2; // 循环条件是:只要两个最值之间有距离就能一直循环,直到元素和中间值相等的时候跳出循环,并返回找到的中间值角标。 while (min <= max) {// 当数组中只有一个元素的时候,两个最值相等。 if (key > arr[mid]) { min = mid + 1; } else if (key < arr[mid]) { max = mid - 1; } else { return mid; } mid = (min + max) / 2; } return -1; }
19.面向对象的三个特点:封装,继承,多态
①封装
对象是用来封装数据的,类似于描述现实场景中的事物,事物包含属性和行为,对应于java中则为成员变量和方法。
封装的概念:隐藏对象的属性(成员变量)和实现细节(方法),仅对外提供公共的访问方式。
②继承
③多态
20.成员变量和局部变量
①作用范围:成员变量作用于整个类中。局部变量作用范围则较小,只作用于方法或是语句(如for循环语句)中。
②在内存中的存在形式:成员变量在于堆内存中,因为对象的存在而存在。局部变量则存在于栈内存中。
③正是因为成员变量存在于堆内存中,成员变量都有默认初始化值,不需要初始化能直接参与运算。而局部变量存在于栈内存中,没有默认初始化值,不执行初始化操作是不能参与运算的。
21.构造函数和一般函数
①构造函数只在对象初始化的时候执行一次,一般函数可以执行多次。
②构造函数的使用:当分析事物时,该事物只要存在就具备一些特性或是行为,那么就将这些内容定义在构造函数中。
22.构造代码块
①作用:给对象进行初始化,对象一建立就执行,且优先于构造函数执行。
②和构造函数的区别:构造代码块是给所有的对象进行统一初始化(不管是哪个构造函数创建出来的对象),定义的是不同对象共性的初始化内容。而构造函数是给对应的构造函数的对象进行初始化。
class Person{ Person(){ System.out.println("Person"); } Person(String name){ System.out.println("Person "+name); } { System.out.println("Person running..."); } public static void main(String[] args){ new Person(); new Person("Jack"); } } --> Person running... Person Person running... Person Jack
23.this关键字和this语句
①this关键字用于区分同名变量(成员变量和局部变量同名)
②this语句用于构造函数间的调用,且只能放在构造函数的第一行(因为初始化要先执行)。另外,一般函数不能直接调用构造函数的,因为this语句不能用在一般函数中,只能在用构造函数中。
class Person{ private String name; private String age; Person(String name){ this.name = name; } Person(String name, String age){ this(name);//如果是普通方法的相互调用,写成Person(name);但这里是构造函数间的调用,所以写成this语句的形式。 this.age = age; } }
24.简单的数据结构:堆栈和队列
堆栈(stack):先进后出,如同一个杯子(生活中常见的容器一般都是堆栈结构的)
队列(Queue):先进先出,如同一个水管
25.Collection
List(元素有序,可重复)
|--ArrayList(底层是数组结构,查询快,增删慢,线程不同步,高效)--保证元素唯一性所依赖的方法是:元素的equals方法
|--LinkedList(底层是链表结构,增删快,查询慢,线程不同步,高效)
|--Vector(底层是数据结构,因为线程同步,低效,查询和增删都较慢)
Set(元素无序,不可重复)
|--HashSet(底层是哈希表结构,线程不同步,高效)--保证元素唯一性所依赖的方法是:先判断元素的hashCode方法,如果该方法的返回值是一样的再判断元素的equals方法
|--TreeSet(底层是二叉树结构,有序,弥补了Set集合无序的不足,线程不同步,高效)
|--让元素自身具备比较性,元素实现comparable接口,重写compareTo方法(这种方式也称之为元素的自然顺序或者叫做默认顺序,即元素一定义完就具备比较性了)。
保证元素唯一性所依赖的方法是:元素的compareTo方法(返回值1,0,-1分别对应大,相等,小)
|--让集合具备比较性(当元素不具备比较性或者具备的比较性不是所需要的时候,这时候就需要让集合具备比较性),实现Compartor接口,重写compare方法,并将接口对象传递给TreeSet的构造函数。
26.泛型类
①当类中的引用数据类型(基本数据类型不行)不确定的时候,定义泛型实现功能的扩展,没有泛型之前的早起做法是定义Object来实现扩展。
②泛型类定义的泛型在整个类中有效,如果泛型类中的泛型被多个方法使用,那么这多个方法中的泛型也是一致的。
③泛型类的类型在泛型对象被创建的时候才被明确具体的数据类型。
④静态方法不能访问类上定义的泛型(因为泛型类在泛型对象被创建的时候才能明确具体的数据类型,而静态先于对象而存在)
27.泛型方法
①为了弥补泛型类的不足,如果有些方法需要操作泛型类类型之外的数据类型,那么可以将泛型定义在方法上。
②静态方法操作的应用数据类型不确定时,只能将泛型定义在方法上(不能定义在类上,因为定义在类上的泛型只有在泛型对象被创建的时候才能明确具体的数据类型,而静态先于对象而存在)
③注意书写:泛型方法定义的泛型的位置是-->返回值类型的前面,修饰符的后面,如:public static <T> void method(){}
28.泛型限定
①? extends E:可以接收E类型或者E的子类型,上限。
②? super E:可以接收E类型或者E类型的父类型,下限。
27.adb(android debug bridge,android调试桥)常见指令
①adb shell,进入linux目录
|--ls,查看当前目录的详细信息
|--ps,查看手机正在运行的进程
|--kill xxx,杀死xxx进程(xxx表示进程id)
|--chmod 777 xxx,更改文件xxx的访问模式为可读可写可执行(rwx)
|--cd data/data/xxx.xxx.xxx/databases
|--sqlite3 person.db,打开指定(person.db)数据库
|--select * from person; 打开person表(注意分号不能省略)
|--rm xxx.txt,移除xxx.txt文件
②adb push xxx.exe /sdcard/xxx.exe,把xxx.exe文件导入到设备的sd卡根目录下
③adb pull /sdcard/xxx.exe aa.exe,把手机sd卡根目录下的xxx.exe文件导出到当前目录(这里的当前目录是指:在哪里执行此adb命令就是那个对应的目录)下,并给文件取名为aa.exe
④adb kill-server,杀死adb的连接调试桥服务;adb start-server,开启adb的连接调试桥服务
执行以上两个命令,可以重启adb调试桥服务。如果以上操作还是不能重启adb服务,那么可以尝试在电脑的任务管理器中结束adb.exe进程(释放adb僵尸进程占用的端口),再次执行以上命令。
⑤adb -s xxx,当电脑连接上多个设备时,通过此命令指定xxx设备为选择的设备。如:adb -s emulator-5554 shell,进入模拟器emulator-5554终端。
28.资源目录res下的文件不能以数字开头,为什么呢?
因为资源目录下的文件都会在R文件中对应生成一个内部类的的引用变量,而这个引用变量的名称正是资源的名称,众所周知变量是不能以数字开头的,只能以字母或是下划线(下划线可行,已实验)开头。
29.当导入一个工程发现没有project.properties文件的时候,这时可以通过new project from existing code的方式导入代码,创建工程。
30.Java性能优化
①尽量使用局部变量,局部变量存在于栈内存中,速度较快,而其它变量,如静态变量、成员变量,这些变量存在于堆内存中,速度较慢。
②尽可能的重用对象,重复创建对象不仅需要花费一定的时间,当对象没有被引用指向时需要被垃圾回收,这也需要花费一定的时间,因此也会对性能带来一定的影响。
③google推荐在android开发中尽量使用静态方法,这比new一个对象,通过对象调用方法,效率要高一些。
31.软件测试
①是否知道源码
|--①白盒测试:知道程序源码的情况下,对具体的方法,程序逻辑等做相应的测试。
|--②黑盒测试:不知道程序源码的情况下,对程序进行测试。黑盒测试一般都有测试用例(user story),即按一定的步骤规则逐步测试软件。
②根据不同的测试粒度
|--①单元测试(unit test):测试一个简单的方法
|--②功能测试(function test):测试某个功能
|--③集成测试(integration test):对多个功能进行联合测试
|--④系统测试(System test):测试某个系统或是平台
③压力测试(pressure test)
④冒烟测试(smoke test):短期内重复调用某个方法
⑤android下的测试
1.在清单文件的application节点下添加代码(声明测试所要用到的类库):
<uses-library android:name="android.test.runner" />
2.在清单文件的根节点下添加代码(声明要被测试的包):
<instrumentation android:name="android.test.InstrumentationTestRunner" android:label="Test for My App" android:targetPackage="xxx.xxx.xxx" />
xxx.xxx.xxx是程序的包名
3.创建测试类继承:AndroidTestCase,在此类中测试需要被测试的方法
32.RAM & ROM & SD卡
①RAM(Ramdom Access Memory):内存,断电数据消失,读取速度快。
②ROM(Read-Only Memory):可理解为硬盘,断电数据不消失,在android中对应的路径是:/data。
常用文件目录:
|--Context.getFilesDir(); --> /data/data/xxx.xxx.xxx/files 一般文件目录
|--Context.getCacheDir(); --> /data/data/xxx.xxx.xxx/cache 缓存文件目录,它和一般上面的一般文件目录的区别是,缓存文件目录下的文件可以在应用程序管理下通过缓存清除按钮手动将缓存文件清除。
|--sp = Context.getSharedPreference(); --> /data/data/xxx.xxx.xxx/shared_prefs
③SD卡:外接的一个存储设备,断电数据不消失,在android中对应的路径是:/mnt/sdcard或者/sdcard,在代码中写成:Environment.getExternalStorageDirectory();
//操作sd数据前,要判断sd卡状态,只有当前sd被挂载上来处于可用状态才能对sd卡进行读写操作.另外操作sd卡需要权限: ①判断sd卡状态权限:<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> ②写sd卡权限:<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { File filesDir = Environment.getExternalStorageDirectory(); }
关于数据的持久化存储,自然是将数据存储在断电数据不消失的ROM或是SD卡中。
33.android log不同的log级别
①v:verbose,提示级别(黑色)
②d:debug,调试级别(蓝色)
③i:info,信息级别(绿色),平常用的最多的System.out.println();在控制台打印的log数据都属于info级别。
④w:warn,警告级别(橙色)
⑤e:error,错误级别(红色)
按照提示的强烈程度排列:verbose<debug<info<warn<error
34.xml解析
①sax解析:基于事件的自上而下的解析,不可返回,内存占用小,较为高效
②dom解析:一次性把文件加载到内存中,生成第一个dom树,较为占用内存,可任意的返回,插入修改数据
③dom4j解析:开源项目
④pull解析:类似于sax的事件解析,代码可读性较好。(android开发一般使用这种解析方式,如果需要在javaee中使用pull,可以将pull的jar包导入工程中)
35.sqlite数据库的增删改查
步骤
①写一个数据库的OpenHelper继承SqLitOpenHelper,在OpenHelper的onCreate方法中创建表结构
②通过helper调用getWritableDatabase方法或是getReadableDatabase方法,获取到sqlite数据库实例
③通过获取到的sqlite实例,执行sql语句,完成对数据库的增删改查操作
面试遇到的问题:通过getWritableDatabase方法和getReadableDatabase方法获取到sqlite数据库实例的区别
答:不管是通过getWritableDatabase方法,还是getReadableDatabase方法,返回其实都是同一个数据库实例。
区别在于:提过查阅源码,得知在返回可写数据库的时候,会数据库进行一个加锁操作,所以多个线程不能同时写一个数据库,但是多个线程(在一定范围内,100左右)能同时读一个数据库。
36.sqlite查询语句
/** * table 要查询的表名 * columns 查询对应的列信息,如:select * from person,这里的查询条件就是*,即查询所有的列,此时columns可以直接填null,也可以将所有的查询列一一列出:new String[]{"id","name","phone"} * selection 查询的条件和selectionArgs对应:如:select * form person where name=?,这里的查询条件就是name=?,而selectionArgs就是?的具体变量参数:new String[] { name }
* 当然如果类似select * from person语句,没有未知变量,则不需要查询条件,此时selection和selectionArgs都为空 * selectionArgs * groupBy 查询的数据如果较多,可以对数据进行分组,对应SQL语句中GROUP BY后面的字符串 * having 分组的条件,对应SQL语句HAVING后面的字符串 * orderBy 对查询结果进行排序,对应SQL语句ORDER BY后面的字符串,ASC为升序排列,DESC为降序排列,如:"id ASC",表示以id的升序排列查询到的结果 * http://notfatboy.iteye.com/blog/653357 */ db.query(table, columns, selection, selectionArgs, groupBy, having, orderBy);
http://www.cnblogs.com/maxinliang/archive/2013/01/22/2871474.html
37.ContentProvider(内容提供者)--把应用程序的私有数据暴露给别的应用程序使用
程序中的数据库文件都是私有的,如果A应用程序的数据库需要暴露出来供B应用程序使用,这时候就使用到了内容提供者。内容提供者是根据对外提供数据uri的方式暴露数据的。
38.ContentResolver(内容解析者)--解析内容提供者暴露的数据
使用内容解析者获取系统联系人的数据
系统联系人数据库位置:/data/data/com.android.provider.contacts/databases/contact2.db
相关源码路径:
\android_all_src\JB\packages\providers\ContactsProvider\AndroidMainfest.xml,在清单配置文件中获取到系统联系人的主机名(authorities):contacts;com.android.contacts,以及所在的类:ContactsProvider2
\android_all_src\JB\packages\providers\ContactsProvider\src\com\android\providers\contacts\ContactsProvider2.java,获取系统联系人uri匹配器(matcher)的路径,根据uri对数据进行相应的操作。
contact.db数据库中的三张较为重要的表:raw_contacts,data,mimetypes
①raw_contacts(主表):记录着联系人的姓名,分组,最后联系时间等字段信息,其中contact_id字段和data表关联
Uri contacts_uri = Uri.parse("content://com.android.contacts/raw_contacts"); Cursor contacts_cursor = resolver.query(contacts_uri, new String[] {"display_name", "contact_id" }, null, null, null);
②data:记录着具体的数据信息,其中raw_contact_id字段等于raw_contacts表的contact_id字段,另外mimetype_id字段和mimrtypes表关联(特别注意这里的列名mimetype_id写成mimetype)
Uri data_uri = Uri.parse("content://com.android.contacts/data"); Cursor data_cursor = resolver.query(data_uri, new String[]{"mimetype", "data1"}, "raw_contact_id=?", new String[] { contact_id }, null);//这里的raw_contact_id字段等于raw_contacts表的contact_id
③mimetypes:记录着数据的具体类型和data表中的mimetype_id字段相关联
使用内容解析者获取系统短信的数据
系统短信数据库位置:/data/data/com.android.providers.telephony/databases/mmssms.db
相关源码路径:
\android_all_src\JB\packages\providers\TelephonyProvider\AndroidMainfest.xml,在清单配置文件中获取到系统联系人的主机名(authorities):sms,以及所在的类:SmsProvider
\android_all_src\JB\packages\providers\TelephonyProvider\src\com\android\providers\telephony\SmsProvider.java,获取系统短信的uri匹配器(matcher)的路径,根据uri对数据进行相应的操作。
39.ContentObserver(内容观察者)
观察某个应用数据库何时发生了变化,相当于数据库的眼睛。
context.getContentResolver().registerContentObserver(uri, true,new MyObserver(new Handler()));
40.布局参数 layout & padding;android:layout_gravity & android:graviry
①layout & padding
layout:控件与控件之间的距离
padding:控件里的内容距离控件边框的距离
②layout_gravity & gravity
gravity:对元素自身来说的,元素自身的文本显示的位置通过这个属性设置,不设置默认是在左侧。
layout_gravity:相对父元素来说的,自定元素显示在父元素的什么位置。
http://www.cnblogs.com/ghj1976/archive/2011/04/26/2029535.html
41.客户端和服务端编码(乱码)问题的处理
关于客户端和服务器端(中文)乱码的问题,解决办法:保证客户端和服务器端编码一致即可。另外tomcat默认编码是iso-8859-1,而android客户端默认编码是utf-8,在处理中文的时候,要在服务器端对字符串进行utf-8或是gbk编码,以保证中文字符能被识别,如果服务端使用utf-8编码,android客户端在接收服务端返回的数据时,可不做编码处理,因为utf-8就是android的默认编码,但是如果服务端使用的是gbk编码,那么android客户端在接收服务器数据时也需要对接收到的数据进行gbk编码处理。android客户端向服务器端传送中文数据同理。(另外直接调用中文编码的方法也可:URLEncode.encode())
①String newdata = new String("Stringdata", "gbk"); ②String newdata = URLEncoder.encode("android客户端向服务端发送的中文数据");//android客户端向服务端提交中文数据(或者特殊字符:% / & 等)必须对数据进行url编码 ③String newdata = new String("服务器端接收的android客户端utf-8编码的中文数据".getBytes("iso-8859-1"), "UTF-8");
42.Get & Post
Get:组拼url的方式提交数据,提交的数据长度有限制(4kb),数据能显示的看到,安全性差
Post:直接将数据以流的形式提交至服务器(conn.setDoOutput(true);),抓包后得知以下请求头字段是Post请求方式独有的,请求数据时一定要记得在请求参数中设置
①Content-Type:application/x-www-form-urlencoded,表示数据以表单的形式提交
②Content-Length:36,表示向服务器提交的数据的长度是36
另外Post请求方式需要手动指定提交的数据
43.httpclient
httpclient是apache开源组织的一个开源项目,android已将此项目集成在android.jar中,httpclient是对浏览器请求网页的封装,模拟现实浏览网页的操作:
①打开一个浏览器 --> 初始化httpclient
②在浏览器输入要访问的地址 --> 准备http请求(get方式或是post方式)
③按下回车键 --> 利用httpclient把http请求发送给服务器
另外即使使用到了中文或是特殊字符,也不用考虑中文编码的问题,因为httpclient内部已经对编码进行了封装处理。
44.activity启动模式
①standard标准启动模式:后进先出的链表
②singleTop启动模式:当栈顶存在的activity是要被激活的activity时,不会重新创建activity,避免了一个已经开启的activity被重复的开启,用户需要按多次的后退键才能退出应用程序。典型应用场景:浏览器书签
此时调用的方法只有:onResume和onNewIntent
③singleTask:当多次开启配置了此模式的activity时,会清空配置了此模式的activity之间的其它的activity实例。配置了此模式的activity的实例是唯一存在的。
④singleInstance:创建新的独立的任务栈,存放配置了此模式的activity实例。新创建的任务栈中只有一个activity实例存在,另外此activity实例在手机中也是唯一存在的。
类似于设计模式中的单例模式。典型应用场景:系统拨号界面。
45.自定义广播
发送自定义广播,通俗来说就是设置广播电台,而广播电台又分为无序广播和有序广播:
①无序广播:异步的操作,所有注册了广播接受者的对象都会接受到这个广播-->sendBroadcast(intent);
无序广播虽然不能终止,但是可滞空,setResultData(null);滞空后,广播也失效了。
②有序广播:广播会按照优先级顺序依次发送给接收者,高优先级(-1000~1000)的广播接收者会先接收到广播事件,并且可以终止或修改广播事件(abortBroadcast();
-->sendOrderedBroadcast(intent,permission);
无序广播没有优先级的概念,有序广播可配置优先级,高优先级的先接受到广播事件,优先级如果相同,则按照配置的先后依次接收到广播事件。<intent-filter android:priority="1000" /><intent-filter>
关于高优先级的数据修改具体来说:通过在高优先级的广播接收者的onReceive方法中设置数据:setResultData();在低优先级的广播接收者中接收到修改的数据:getResultData();
另外有序广播还有一个重载方法:sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler, initialCode, initialData, initialExtras);此方法如果参数三设定了接收者,则此接收者是
无论如何都会接收到广播的,即使在此接收者之前的广播执行了abortBroadcast();方法。
③粘性广播:普通的广播生命周期只有短短的十秒,而粘性广播则弥补了这一点,它会一直保留到广播事件执行结束。典型应用场景:系统wifi的开启,是一个较为耗时的操作,可能会大于10秒,这里就是用到了
粘性广播。
sendStickyBroadcast(intent);
④由于广播是没有界面,没有任务栈的。所以在广播接收者中开启Activity时,需要手动将Activity添加到任务栈中。添加代码:intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);服务中同理。
电台
Intent intent = new Intent(); intent.setAction("com.ngu.mybroadcastreceiver");//自定义广播电台 intent.putExtra("info", "额外的数据信息"); sendBroadcast(intent);
收音机
<-- 清单文件中配置要接收的广播 --> <receiver android:name=".MyBroadcastReceiver"> <intent-filter> <action android:name="com.ngu.mybroadcastreceiver" /> </intent-filter> </receiver>
46.进程优先级
http://developer.android.com/guide/components/processes-and-threads.html
http://blog.csdn.net/su1216/article/details/7869498
①前台进程:
有一个获取到焦点的activity对应的进程;和用户交互的activity绑定在一起的service对应的进程;有一个正在调用startForeground方法或是onCreate,onStart,onDestroy生命周期相关的方法的service对
应的进程;正在执行onReceive方法的广播接收者对应的进程。
②可见进程:失去焦点用户可见的activity对应的进程;和用户可见的activity绑定在一起的service对应的进程。
③服务进程:service正在执行startServic方法,即正在后台运行的服务对应的进程。(提升服务的优先级:setForeground(true);如果服务执行了此方法,此服务进程就提升为了前台进程。)
④后台进程:执行了onStop方法的activity(此时用户不可见)对应的进程。
⑤空进程:进程里没有任何系统组件(activity,service,broadcastreceiver)存在。系统在内存不足的时候,会回收此进程。
以上进程按照优先级递减的次序排列,低优先级的进程优先被系统回收。
47.服务的两种开启方式及其生命周期(key:耗时,后台)
①startService(调用者退出了,服务还在后台运行,也就是说服务和调用者的生命周期没有关系)
1)服务只会被创建一次(调用onCreate方法和onStart方法),多次开启服务只会调用onStart方法。(特有回调方法:onStart)
2)服务停止的时候(通过在调用者中:stopService方法停止服务)执行onDestroy方法。
②bindService(调用者退出,服务也跟着结束,服务的生命周期和调用者同步)
1)服务只会被创建一次(调用onCreate方法和onBind方法),onBind方法和onCreate方法均只在第一次创建时调用一次,多次绑定服务不再调用。(特有回调方法:onBind)
2)服务停止的时候执行onDestroy方法和onUnbind方法。
3)服务只能被解除绑定(通过在调用者中:unbindService方法解绑)一次,多次解绑会异常。
以上要分清调用者中的方法和服务中的生命周期相关的方法,总的来说:如果是startService方式开启服务,如果需要停止服务,调用者中调用stopService(serviceIntent)方法。如果是bindService方式开启服
务,如果需要解除绑定服务,调用者中调用unbindService(conn)方法。剩下的其他方法都是service生命周期中的方法。
48.bindService
①简单说明:通过绑定服务的方式开启服务,就目的而言,一般来说是为了调用服务中的方法。java中方法的最常见调用方式:创建对象,通过对象实例,调用方法。而通过绑定方式开启的服务,我们是无法获取
到服务对象的,因为服务对象的创建都是系统框架完成的。所以绑定方式开启服务,调用服务中的方法就不能通过普通的对象调用实现。
②具体实现:通过bindService方式开启服务,服务绑定成功,对于服务和调用者来说,服务中会调用onBind方法方法,调用者的ServiceConnection接口实现类中会调用onServiceConnected方法。具体来说,
onBinder方法返回值是一个IBinder对象(可以通过此对象间接的调用服务中的方法),而onServiceConnected方法参数中接收一个IBinder对象,此对象就是服务onBinder方法返回的对象。利用此对象为中间
人,间接的调用服务中的方法。
③细节注意:通过服务中的IBinder对象的自定义方法调用服务中的指定方法,此自定义方法也就是需要暴露出去的方法,对于需要暴露出去的方法,一般而言通过接口的方式把方法抽取出来。
http://www.cnblogs.com/wipedata/p/3147540.html
49.IPC & AIDL
①IPC:Inter-ProcessCommunication,进程间通信
②AIDL:Android Interface Definition Language,Android接口定义语言
50.屏幕适配
<supports-screens android:largeScreens="true" android:normalScreens="false" android:smallScreens="true" android:resizeable="true" android:anyDensity="true"/>
blalalalalal......http://www.cnblogs.com/wipedata/p/3169252.html
51.Url & Uri
url:统一资源定位符,如:http:// ftp:// https:// rstp://
uri:统一资源标识符,它描述的范围更加广泛一些,只要符合这样的规则:有一个前缀加一个冒号,这样的路径都可以理解成是uri,如拨号ContactProvider中的,tel:125,表示要拨打的号码为125
52.raw & assets
project
|-- src(c.jpg)
|-- gen
|-- assets(b.jpg)
|--fonts(xxx.ttf)
|-- bin
|-- libs
|-- res
|-- anim
|-- drawable
|-- layout
|-- menu
|-- raw(a.jpg)
|-- values
|-- xml
AndroidManifest.xml
proguard-project.txt
proguard-project.txt
①raw:这种资源使用方式,会在R文件中生成id引用,当文件过大的时候,不适合使用这种方式(没有目录结构,即不能有二级目录)
InputStream is = getResources().openRawResource(R.raw.a); (R.raw.filename)
②assets:这种资源使用方式的特点是:把资源原封不动的打包到应用程序的apk中,不会在R文件中生成id引用,资源没有大小限制(可以有目录结构)
InputStream is = context.getAssets().open("b.jpg"); (filename.suffix)
③使用类加载器,加载资源文件
InputStream is = getClass().getClassLoader().getResourceAsStream("c.jpg"); (filename.suffix)
④raw和assets的区别(http://my.eoe.cn/futurexiong/archive/5350.html)
由于raw是Resources (res)的子目录,Android会自动的为这目录中的所有资源文件生成一个ID,这个ID会被存储在R类当中,作为一个文件的引用。这意味着这个资源文件可以很容易的被Android的类和方法访
问到,甚至在Android XML文件中你也可以@raw/的形式引用到它。在Android中,使用ID是访问一个文件最快捷的方式。MP3和Ogg文件放在这个目录下是比较合适的。
assets目录更像一个附录类型的目录,Android不会为这个目录中的文件生成ID并保存在R类当中,因此它与Android中的一些类和方法兼容度更低。同时,由于你需要一个字符串路径来获取这个目录下的文件描述
符,访问的速度会更慢。但是把一些文件放在这个目录下会使一些操作更加方便,比方说拷贝一个数据库文件到系统内存中。要注意的是,你无法在Android XML文件中引用到assets目录下的文件,只能通过
AssetManager来访问这些文件。数据库文件和游戏数据等放在这个目录下是比较合适的。
53.自定义圆角图片(美工什么的都是浮云)
http://www.cnblogs.com/wipedata/p/3170769.html
54.activity生命周期
对于一些需要持久化保存的数据,必须在onPause方法中进行处理,因为onStop和onDestroy方法不一定会被调用。
55.fragment生命周期
1.首先fragment需要附加到指定的activity上,执行onAttach方法
2.执行onCreate方法和onCreateView方法,创建fragment对应的view对象
3.activity创建的时候,对应的在fragment中会执行onActivityCreated方法
4.fragment用户可见,先后执行onStart(可见),onResume(获取到焦点)方法
5.fragment退出,先后执行onPause(失去焦点),onStop(不可见)方法
6.fragment销毁,先执行onDestroyView,销毁view对象,而后销毁自己,执行onDestroy方法,最后把fragment和activity之间关联的引用销毁,执行onDetach方法
以上较为关心的方法有:onCreateView,类似于BaseAdapter中的getView,可以参照理解其作用-->创建view对象,通过inflate布局填充器(可以很方便的将xml布局转换成view对象)可以灵活的自定义布局
http://blog.csdn.net/xu_fu/article/details/8257367
56.判断服务是否开启
public class ServiceInfoUtil { public static boolean isStartService(Context context){ boolean result = false; ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<RunningServiceInfo> runningServices = am.getRunningServices(30); for(RunningServiceInfo runningService : runningServices){ String className = runningService.service.getClassName(); if("com.ngu.test.MyService".equals(className)){ result = true; System.out.println("MyService服务已开启"); } } return result; } }
以上其实就是判断系统正在运行的服务的集合里是否包含有指定的服务
57.数据库
①建立表结构
自定义类:XXXDBOpenHelper,继承SQLiteOpenHelper,在构造方法中指定数据库名,游标工厂(可为null),以及版本号信息。在onCreate方法中创建表结构,在onUpgrade方法中更新表结构,此方法放在
数据库版本号变更时调用。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table mytable (_id integer primary key autoincrememt, number varchar(20), name varchar(20))"); }
②获取数据库实例
自定义类XXXDao,通过以上的XXXDBOpenHelper,获取到SQLiteDataBase(helper.getWritableDatabase()/helper.getReadableDatabase--可读数据或是可写数据)数据库实例
③实现增删改查方法:通过获取到的sqlite实例,执行sql语句,完成对数据库的增删改查操作
58.ImageView中的src和background的区别
①两者如果同时设置时,src在前(前景),background在后(背景)。
②使用src时,可配合ImageView的scaleType属性一起使用,scaleType对background无效。
③src中存放的是原图,不可拉伸,background中的资源可拉伸。
④scaleType属性详解
CENTER/center 在视图中心显示图片,并且不缩放图片
CENTER_CROP/centerCrop 按比例缩放图片,使得图片长 (宽)的大于等于视图的相应维度
CENTER_INSIDE/centerInside 按比例缩放图片,使得图片长 (宽)的小于等于视图的相应维度
FIT_CENTER/fitCenter 按比例缩放图片到视图的最小边,居中显示
FIT_END/fitEnd 按比例缩放图片到视图的最小边,显示在视图的下部分位置
FIT_START/fitStart 把图片按比例扩大/缩小到视图的最小边,显示在视图的上部分位置
FIT_XY/fitXY 把图片不按比例缩放到视图的大小显示
MATRIX/matrix 用矩阵来绘制
http://blog.sina.com.cn/s/blog_4e1e357d0101b3da.html
59.ProgressBar
android:progressBarStyle:默认进度条样式,不确定模式
android:progressBarStyleHorizontal:水平进度条样式
android:progressBarStyleLarge :大号进度条样式,也是不确定进度模式
android:progressBarStyleSmall :小号进度条样式,也是不确定进度模式
xml文件中的水平样式:style="?android:attr/progressBarStyleHorizontal"
60.屏幕常亮的实现
①在activity的onCreata方法中添加以下代码,可不用加权限
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
②在xml文件中添加以下代码,并在清单文件中加上权限:<uses-permission android:name="android.permission.WAKE_LOCK" />
public class Test extends Activity { PowerManager powerManager = null; WakeLock wakeLock = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(R.layout.main); this.powerManager = (PowerManager)this.getSystemService(Context.POWER_SERVICE); this.wakeLock = this.powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "My Lock"); } @Override protected void onResume() { super.onResume(); this.wakeLock.acquire();//请求常亮 } @Override protected void onPause() { super.onPause(); this.wakeLock.release();//取消屏幕常亮,如果不调用WakeLock.release,则屏幕会一直常亮 } }
61.自定义字体
两行代码,就这么简单:引用资源目录access二级目录font下的字体文件,再将字体文件设置给相应的字体即可
Typeface tf = Typeface.createFromAsset(getAssets(), "font/mytf.ttf");
tv_page1_loading.setTypeface(tf);
62.获取文件扩展名
系统API默认提供一个MimeTypeMap类来检索,识别文件扩展名
String fileExtension = MimeTypeMap.getFileExtensionFromUrl(url);
63.TextView文本间距设置 & 下划线
Android系统中TextView默认显示中文时会比较紧凑,不是很美观。为了让每行保持一定的行间距,可以设置属性android:lineSpacingExtra(设置行间距)或android:lineSpacingMultiplier(设置行间距的倍数)
关于Android下TextView中文换行问题,可查看Android自定义view-文本自动换行。
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:lineSpacingExtra="3dp" android:lineSpacingMultiplier="1.5" android:textStyle="bold" />
文本下划线:textview.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG);
文本删除线:textview.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
设置换行文字间距:android:lineSpacingExtra="6sp"
设置初始化提示文字颜色:android:textColorHint="@color/white" <edittext>
设置文字样式:setTextAppearance(R.style.TextLargeStyle),对应到xml文件中就是:style="@style/TextLargeStyle"。
64.onInterceptTouchEvent & onTouchEvent
onInterceptTouchEvent()用于处理事件并改变事件的传递方向。onInterceptTouchEvent()的默认返回值是false,这样才能继续向子view传递事件,如果修改为true,则事件只传递到当前view的onTouchEvent。
onTouchEvent()用于处理事件,返回值决定当前控件是否消费(consume)了这个事件。onTouchEvent()的默认返回值是true,表示为消费了此次事件,比如先响应点击事件down,接下来才依次响应事件move和up。如果在响
应down事件的时候,返回值修改为false,则表示消费了此次事件,也就不会执行之后的down和up事件了。
65.HttpClient请求服务器,请求超时设置
方式一:在构造函数中传入初始化参数的方式设置
private static final int CONNECTION_TIME_OUT = 6000; private static final int SOCKET_TIME_OUT = 5000; private static final long CONNMANAGER_TIME_OUT = 3000; HttpParams params = new BasicHttpParams(); /* 从连接池中取连接的超时时间 */ ConnManagerParams.setTimeout(params, CONNMANAGER_TIME_OUT); /* 连接超时 */ HttpConnectionParams.setConnectionTimeout(params, CONNECTION_TIME_OUT); /* 请求超时 */ HttpConnectionParams.setSoTimeout(params, SOCKET_TIME_OUT); DefaultHttpClient client = new DefaultHttpClient(params);
方式二:空参数的构造函数创建的httpclient对象直接设置超时时长
DefaultHttpClient client = new DefaultHttpClient(); //连接超时 client.getParams().setParameter("http.connection.timeout", CONNECTION_TIME_OUT); //请求超时 client.getParams().setParameter("http.socket.timeout", SOCKET_TIME_OUT);
66.ListView和GridView滚动条的显示和隐藏
android:fastScrollAlwaysVisible="true"<大号滚动条>,android:scrollbars="none"<小号滚动条隐藏>
67.四舍五入取小数点后两位
①NumberFormat
NumberFormat formatter = new DecimalFormat("#0.00"); [三位:"#0.000",四位:"#0.0000",以此类推]
String formatedNumber = formatter.format(formatNumber);
②BigDecimal.setScale
BigDecimal.setScale()方法用于格式化小数点
setScale(1)表示保留一位小数,默认用四舍五入方式
setScale(1,BigDecimal.ROUND_DOWN)直接删除多余的小数位,如2.35会变成2.3
setScale(1,BigDecimal.ROUND_UP)进位处理,2.35变成2.4
setScale(1,BigDecimal.ROUND_HALF_UP)四舍五入,2.35变成2.4
setScaler(1,BigDecimal.ROUND_HALF_DOWN)四舍五入,2.35变成2.3,如果是5则向下舍
http://blog.csdn.net/ahwr24/article/details/7048724
68.this语句(java基础)
this语句用于构造函数间的调用。如
public class Test { public Test(int x, int y) { } public Test(int x ,int y, int z) { this(x, y); } }
69.更新字符串中的部分数据信息
String strLog = String.format("您当前的位置:\r\n" +"纬度:%f\r\n" +"经度:%f",location.getLongitude(), location.getLatitude());
<string name="data">整数型:%1$d,浮点型:%2$.2f,字符串:%3$s</string>
其中%后面是占位符的位置,从1开始,$ 后面是填充数据的类型,%d:表示整数,%f :表示浮点型,其中f前面的.2表示小数的位,%s:表示字符串
String data = getResources().getString(R.string.data);
data = String.format(data, 100, 15.2, "2014-02-12");
1$ 2$ 3$ 这些表示要填充的数据的位置,当只有一个数据为未知需要填充时,可以省去不写,如:<string name="retrieve">重新获取(%s)</string>
http://www.2cto.com/kf/201108/99632.html
70.应用图标不同分辨率屏幕下的大小
ldpi mdpi hdpi
Launcher 36 x 36 px 48 x 48 px 72 x 72 px
Menu 36 x 36 px 48 x 48 px 72 x 72 px
Status Bar 24 x 24 px 32 x 32 px 48 x 48 px
Tab 24 x 24 px 32 x 32 px 48 x 48 px
Dialog 24 x 24 px 32 x 32 px 48 x 48 px
List View 24 x 24 px 32 x 32 px 48 x 48 px
71.换行符‘\n’和回车符‘\r’
'\n' 10,\x0a 换行(newline)换行符:另起一行
'\r' 13,\x0d 回车(return)回车符:回到一行的开头
所以平常写的\r\n,应该称作“换行回车符”
windows平台下的回车换行:\r\n。Linux平台下的回车换行:\n,因为Linux平台下没有\r符号。
http://www.cnblogs.com/jacktu/archive/2008/06/12/1218400.html
72.什么时候需要实现Serializable接口
当对象需要被持久化的时候。当客户端和服务端交互,远程方法调用(rpc)的时候。
序列化接口的作用是可以将一个对象实例序列化,序列化后你可以选择将它保存在需要的位置。
另外需要注意,序列化的对象中包含的属性和其他对象都需要实现序列化接口,不然无法正常序列化。
73.Color
view.setBackgroundColor(Color.RED);
view.setBackgroundColor(Color.rgb(255, 0, 0));
view.setBackgroundColor(getResource().getColor(R.color.red));
74..9(9Patch图片)
left和top边框的交叉区域是可拉伸部分
right和bottom边框的交叉区域是内容部分(可选)
http://www.cnblogs.com/qianxudetianxia/archive/2011/04/17/2017591.html
75.eclipse常用快捷键
Ctrl+Q 定位到最后编辑的地方
Ctrl+M 最大化当前窗口
Ctrl+Shift+↑(↓) 快速定位到当前位置对应的上一个方法或下一个方法
76.eclipse配置细节
①调整xml文字大小:Window-->Preferences-->General-->Appearance-->Colors and Fonts-->Basic-->Text Font-->11/小五/五号
②修改背景色(眼科专家推荐色:绿豆沙色):Window-->Preferences-->General-->Editors-->Text Editors-->Appearance color options:-->Background color-->Color-->规定自定义颜色-->色调:85,饱和度:123,亮度205
③高亮设置:直接在搜索框中输入:Occurrences,在搜索结果中筛选:Java--Eitor-->Mark Occurrences,把该目录下的对勾都选上即可,或者快捷键Alt+Shift+O。
76.android sdk manager下载问题
因为天.chao.把android开发网站墙了,sdk manager下载时受影响的域名是:dl-ssl.google.com。
解决办法:通过修改host文件访问dl-ssl.google.com,用记事本打开C:\WINDOWS\system32\drivers\etc中的hosts文件,在hosts文件里添加dl-ssl.google.com,以及其映射的ip,ip在不同的时间段可能会不一样,ip获取方法:http://ip.chinaz.com/?IP=dl-ssl.google.com
77.Frame帧动画
①在res/anim下定义xml动画文件:anim.xml
<?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:apk="http://schemas.android.com/apk/res/android" apk:oneshot="false"> <item apk:drawable="@drawable/ic_launcher" apk:duration="300" /> <item apk:drawable="@drawable/ic_launcher_" apk:duration="300" /> </animation-list>
②在代码中引用动画,并开启
ImageView iv = new ImageView(context); iv.setBackgroundResource(R.anim.anim); AnimationDrawable anim = (AnimationDrawable)iv.getBackground(); anim.start();
③以上,也可直接在代码中创建帧动画
private AnimationDrawable createAnim(int duration, boolean play, Drawable... frames) { AnimationDrawable animationDrawable = new AnimationDrawable(); animationDrawable.setOneShot(false); for (int i = 0; i < frames.length; i++) { animationDrawable.addFrame(frames[i], duration); } animationDrawable.setAlpha(255); if (play) { animationDrawable.start(); } return animationDrawable; } private void invoke(ImageView iv) { AnimationDrawable anim = createAnim(500, false, new Drawable[] { getResources().getDrawable(R.drawable.ic_launcher), getResources().getDrawable(R.drawable.ic_launcher_) }); iv.setBackgroundDrawable(anim); anim.start(); }
78.RelativeLayout
int ALIGN_LEFT(ALIGN_RIGHT/ALIGN_TOP/ALIGN_BOTTOM)
Rule that aligns a child's left(right/top/bottom) edge with another child's left(right/top/bottom) edge.
排列对齐子视图的左(右/上/下)边缘和其他子视图的左(右/上/下)边缘
int ALIGN_PARENT_LEFT(ALIGN_PARENT_RIGHT/ALIGN_PARENT_TOP/ALIGN_PARENT_BOTTOM)
Rule that aligns the child's left(right/top/bottom) edge with its RelativeLayout parent's left(right/top/bottom) edge.
排列对齐子视图的左(右/上/下)边缘和他的RelativeLayout父类的左(右/上/下)边缘
int LEFT_OF(RIGHT_OF/ABOVE/BOTTOM)
Rule that aligns a child's right(left/bottom/top) edge with another child's left(right/top/bottom) edge.
排列对齐子视图的右(左/下/上)边缘和其他子视图的左(右/上/下)边缘
http://developer.android.com/reference/android/widget/RelativeLayout.html
79.最基本的IO操作:将String字符串以文件的形式存储在sd卡[代码片段]
protected static void saveJsonData2SD(String json){ try { File file = new File(Environment.getExternalStorageDirectory(), System.currentTimeMillis()+"__testtest.txt"); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "utf-8")); bw.write(json); bw.close(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
80.避免按钮点击过快
private static long mLastClickTime; // avoid click too fast. public static boolean isFastClick(long bearTime) { long time = System.currentTimeMillis(); long timeInterval = time - mLastClickTime; if (0 < timeInterval && timeInterval < bearTime) { return true; } mLastClickTime = time; return false; }