当前位置:  编程技术>移动开发
本页文章导读:
    ▪java通配符<&gt        java通配符<?> 泛型是一种表示类或方法行为对于未知类型的类型约束的方法,比如 “不管这个方法的参数 x 和 y 是哪种类型,它们必须是相同的类型”,“必须为这些方法提供同一类型.........
    ▪ 应用CharBuffer和 InputStreamReader读取各种编码的网页        使用CharBuffer和 InputStreamReader读取各种编码的网页 只要指明编码格式,就能正确的读取 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.nio.CharB.........
    ▪ objective-C 的内存储器管理之-引用计数       objective-C 的内存管理之-引用计数   obj-c本质就是"改进过的c语言",大家都知道c语言是没有垃圾回收(GC)机制的(注:虽然obj-c2.0后来增加了GC功能,但是在iphone上不能用,因此对于iOS平台的程序.........

[1]java通配符<&gt
    来源: 互联网  发布时间: 2014-02-18
java通配符<?>

泛型是一种表示类或方法行为对于未知类型的类型约束的方法,比如 “不管这个方法的参数 x 和 y 是哪种类型,它们必须是相同的类型”,“必须为这些方法提供同一类型的参数” 或者 “foo() 的返回值和 bar() 的参数是同一类型的”。

通配符 — 使用一个奇怪的问号表示类型参数 — 是一种表示未知类型的类型约束的方法。通配符并不包含在最初的泛型设计中(起源于 Generic Java(GJ)项目),从形成 JSR 14 到发布其最终版本之间的五年多时间内完成设计过程并被添加到了泛型中。

通配符在类型系统中具有重要的意义,它们为一个泛型类所指定的类型集合提供了一个有用的类型范围。对泛型类 ArrayList 而言,对于任意(引用)类型 T,ArrayList<?> 类型是 ArrayList<T> 的超类型(类似原始类型 ArrayList 和根类型 Object,但是这些超类型在执行类型推断方面不是很有用)。

通配符类型 List<?> 与原始类型 List 和具体类型 List<Object> 都不相同。如果说变量 x 具有 List<?> 类型,这表示存在一些 T 类型,其中 x 是 List<T>类型,x 具有相同的结构,尽管我们不知道其元素的具体类型。这并不表示它可以具有任意内容,而是指我们并不了解内容的类型限制是什么 — 但我们知道存在 某种限制。另一方面,原始类型 List 是异构的,我们不能对其元素有任何类型限制,具体类型 List<Object> 表示我们明确地知道它能包含任何对象(当然,泛型的类型系统没有 “列表内容” 的概念,但可以从 List 之类的集合类型轻松地理解泛型)。

通配符在类型系统中的作用部分来自其不会发生协变(covariant)这一特性。数组是协变的,因为 Integer 是 Number 的子类型,数组类型 Integer[] 是 Number[] 的子类型,因此在任何需要 Number[] 值的地方都可以提供一个 Integer[] 值。另一方面,泛型不是协变的, List<Integer> 不是 List<Number> 的子类型,试图在要求 List<Number> 的位置提供 List<Integer> 是一个类型错误。这不算很严重的问题 — 也不是所有人都认为的错误 — 但泛型和数组的不同行为的确引起了许多混乱。

我已使用了一个通配符 — 接下来呢?

清单 1 展示了一个简单的容器(container)类型 Box,它支持 put 和 get 操作。 Box 由类型参数 T 参数化,该参数表示 Box 内容的类型, Box<String> 只能包含 String 类型的元素。



   清单 1. 简单的泛型 Box 类型

              

public interface Box<T> {

    public T get();

    public void put(T element);

}

通配符的一个好处是允许编写可以操作泛型类型变量的代码,并且不需要了解其具体类型。例如,假设有一个 Box<?> 类型的变量,比如清单 2 unbox() 方法中的 box 参数。unbox() 如何处理已传递的 box?



   清单 2. 带有通配符参数的 Unbox 方法

              

public void unbox(Box<?> box) {

    System.out.println(box.get());

}

事实证明 Unbox 方法能做许多工作:它能调用 get() 方法,并且能调用任何从 Object 继承而来的方法(比如 hashCode())。它惟一不能做的事是调用 put() 方法,这是因为在不知道该 Box 实例的类型参数 T 的情况下它不能检验这个操作的安全性。由于 box 是一个 Box<?> 而不是一个原始的 Box,编译器知道存在一些 T 充当 box 的类型参数,但由于不知道 T 具体是什么,您不能调用 put() 因为不能检验这么做不会违反 Box 的类型安全限制(实际上,您可以在一个特殊的情况下调用 put():当您传递 null 字母时。我们可能不知道 T 类型代表什么,但我们知道 null 字母对任何引用类型而言是一个空值)。

关于 box.get() 的返回类型,unbox() 了解哪些内容呢?它知道 box.get() 是某些未知 T 的 T,因此它可以推断出 get() 的返回类型是 T 的擦除(erasure),对于一个无上限的通配符就是 Object。因此清单 2 中的表达式 box.get() 具有 Object 类型。

通配符捕获

清单 3 展示了一些似乎应该可以工作的代码,但实际上不能。它包含一个泛型 Box、提取它的值并试图将值放回同一个 Box。



   清单 3. 一旦将值从 box 中取出,则不能将其放回

              

public void rebox(Box<?> box) {

    box.put(box.get());

}



Rebox.java:8: put(capture#337 of ?) in Box<capture#337 of ?> cannot be applied

   to (java.lang.Object)

    box.put(box.get());

       ^

1 error

这个代码看起来应该可以工作,因为取出值的类型符合放回值的类型,然而,编译器生成(令人困惑的)关于 “capture#337 of ?” 与 Object 不兼容的错误消息。

“capture#337 of ?” 表示什么?当编译器遇到一个在其类型中带有通配符的变量,比如 rebox() 的 box 参数,它认识到必然有一些 T ,对这些 T 而言 box 是 Box<T>。它不知道 T 代表什么类型,但它可以为该类型创建一个占位符来指代 T 的类型。占位符被称为这个特殊通配符的捕获(capture)。这种情况下,编译器将名称 “capture#337 of ?” 以 box 类型分配给通配符。每个变量声明中每出现一个通配符都将获得一个不同的捕获,因此在泛型声明 foo(Pair<?,?> x, Pair<?,?> y) 中,编译器将给每四个通配符的捕获分配一个不同的名称,因为任意未知的类型参数之间没有关系。

错误消息告诉我们不能调用 put(),因为它不能检验 put() 的实参类型与其形参类型是否兼容 — 因为形参的类型是未知的。在这种情况下,由于 ? 实际表示 “?extends Object” ,编译器已经推断出 box.get() 的类型是 Object,而不是 “capture#337 of ?”。它不能静态地检验对由占位符 “capture#337 of ?” 所识别的类型而言 Object 是否是一个可接受的值。

捕获助手

虽然编译器似乎丢弃了一些有用的信息,我们可以使用一个技巧来使编译器重构这些信息,即对未知的通配符类型命名。清单 4 展示了 rebox() 的实现和一个实现这种技巧的泛型助手方法(helper):



清单 4. “捕获助手” 方法

              

public void rebox(Box<?> box) {

    reboxHelper(box);

}



private<V> void reboxHelper(Box<V> box) {

    box.put(box.get());

}

助手方法 reboxHelper() 是一个泛型方法,泛型方法引入了额外的类型参数(位于返回类型之前的尖括号中),这些参数用于表示参数和/或方法的返回值之间的类型约束。然而就 reboxHelper() 来说,泛型方法并不使用类型参数指定类型约束,它允许编译器(通过类型接口)对 box 类型的类型参数命名。

捕获助手技巧允许我们在处理通配符时绕开编译器的限制。当 rebox() 调用 reboxHelper() 时,它知道这么做是安全的,因为它自身的 box 参数对一些未知的 T 而言一定是 Box<T>。因为类型参数 V 被引入到方法签名中并且没有绑定到其他任何类型参数,它也可以表示任何未知类型,因此,某些未知 T 的 Box<T> 也可能是某些未知 V 的 Box<V>(这和 lambda 积分中的 α 减法原则相似,允许重命名边界变量)。现在 reboxHelper() 中的表达式 box.get() 不再具有 Object 类型,它具有 V 类型 — 并允许将 V 传递给 Box<V>.put()。

我们本来可以将 rebox() 声明为一个泛型方法,类似 reboxHelper(),但这被认为是一种糟糕的 API 设计样式。此处的主要设计原则是 “如果以后绝不会按名称引用,则不要进行命名”。就泛型方法来说,如果一个类型参数在方法签名中只出现一次,它很有可能是一个通配符而不是一个命名的类型参数。一般来说,带有通配符的 API 比带有泛型方法的 API 更简单,在更复杂的方法声明中类型名称的增多会降低声明的可读性。因为在需要时始终可以通过专有的捕获助手恢复名称,这个方法让您能够保持 API 整洁,同时不会删除有用的信息。

类型推断

捕获助手技巧涉及多个因素:类型推断和捕获转换。Java 编译器在很多情况下都不能执行类型推断,但是可以为泛型方法推断类型参数(其他语言更加依赖类型推断,将来我们可以看到 Java 语言中会添加更多的类型推断特性)。如果愿意,您可以指定类型参数的值,但只有当您能够命名该类型时才可以这样做 — 并且不能够表示捕获类型。因此要使用这种技巧,要求编译器能够为您推断类型。捕获转换允许编译器为已捕获的通配符产生一个占位符类型名,以便对它进行类型推断。

当解析一个泛型方法的调用时,编译器将设法推断类型参数它能达到的最具体类型。例如,对于下面这个泛型方法:

public static<T> T identity(T arg) { return arg };

和它的调用:

Integer i = 3;

System.out.println(identity(i));

编译器能够推断 T 是 Integer、Number、 Serializable 或 Object,但它选择 Integer 作为满足约束的最具体类型。

当构造泛型实例时,可以使用类型推断减少冗余。例如,使用 Box 类创建 Box<String> 要求您指定两次类型参数 String:

Box<String> box = new BoxImpl<String>();

即使可以使用 IDE 执行一些工作,也不要违背 DRY(Don't Repeat Yourself)原则。然而,如果实现类 BoxImpl 提供一个类似清单 5 的泛型工厂方法(这始终是个好主意),则可以减少客户机代码的冗余:



清单 5. 一个泛型工厂方法,可以避免不必要地指定类型参数

              

public class BoxImpl<T> implements Box<T> {



    public static<V> Box<V> make() {

        return new BoxImpl<V>();

    }



    ...

}

如果使用 BoxImpl.make() 工厂实例化一个 Box,您只需要指定一次类型参数:

Box<String> myBox = BoxImpl.make();

泛型 make() 方法为一些类型 V 返回一个 Box<V>,返回值被用于需要 Box<String> 的上下文中。编译器确定 String 是 V 能接受的满足类型约束的最具体类型,因此此处将 V 推断为 String。您还可以手动地指定 V 的值:

Box<String> myBox = BoxImpl.<String>make();

除了减少一些键盘操作以外,此处演示的工厂方法技巧还提供了优于构造函数的其他优势:您能够为它们提高更具描述性的名称,它们能够返回命名返回类型的子类型,它们不需要为每次调用创建新的实例,从而能够共享不可变的实例(参见参考资料中的 Effective Java, Item #1,了解有关静态工厂的更多优点)。

结束语

通配符无疑非常复杂:由 Java 编译器产生的一些令人困惑的错误消息都与通配符有关,Java 语言规范中最复杂的部分也与通配符有关。然而如果使用适当,通配符可以提供强大的功能。此处列举的两个技巧 — 捕获助手技巧和泛型工厂技巧 — 都利用了泛型方法和类型推断,如果使用恰当,它们能显著降低复杂性。

    
[2] 应用CharBuffer和 InputStreamReader读取各种编码的网页
    来源: 互联网  发布时间: 2014-02-18
使用CharBuffer和 InputStreamReader读取各种编码的网页

只要指明编码格式,就能正确的读取
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.CharBuffer;

public class PageParser {

	public static void main(String args[]) {
		BufferedReader in = null;
		try {
			in = new BufferedReader(new InputStreamReader(new URL(
					"http://news.cnool.net/0-1-19/35941/3.html").openStream(),
					"utf-8"));
		} catch (Exception e2) {
			e2.printStackTrace();
		}
		CharBuffer bos = CharBuffer.allocate(20480);
		int read = 0;
		StringBuilder sb = new StringBuilder();
		try {
			while (in.read(bos) != -1) {
				bos.flip();
				sb.append(bos.toString());
			}
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		System.out.println(sb.toString());
	}
}
 

    
[3] objective-C 的内存储器管理之-引用计数
    来源: 互联网  发布时间: 2014-02-18
objective-C 的内存管理之-引用计数

 

obj-c本质就是"改进过的c语言",大家都知道c语言是没有垃圾回收(GC)机制的(注:虽然obj-c2.0后来增加了GC功能,但是在iphone上不能用,因此对于iOS平台的程序员来讲,这个几乎没啥用),所以在obj-c中写程序时,对于资源的释放得由开发人员手动处理,相对要费心一些。

引用计数

这是一种古老但有效的内存管理方式。每个对象(特指:类的实例)内部都有一个retainCount的引用计数,对象刚被创建时,retainCount为1,可以手动调用retain方法使retainCount+1,同样也可以手动调用release方法使retainCount-1,调用release方法时,如果retainCount值减到0,系统将自动调用对象的dealloc方法(类似于c#中的dispose方法),开发人员可以在dealloc中释放或清理资源。

1、基本用法

为了演示这种基本方式,先定义一个类Sample

类接口部分Sample.h

//
//  Sample.h
//  MemoryManage_1
//
//  Created by jimmy.yang on 11-2-19.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//
  
#import <Foundation/Foundation.h>
  
  
@interface Sample : NSObject {
  
}
  
@end

类实现部分Sample.m

//
//  Sample.m
//  MemoryManage_1
//
//  Created by jimmy.yang on 11-2-19.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//
  
#import "Sample.h"
  
  
@implementation Sample
  
-(id) init
{
    if (self=[super init]){
        NSLog(@"构造函数被调用了!当前引用计数:%d",[self retainCount]);
    }
    return (self);
}
  
-(void) dealloc{
    NSLog(@"析构函数将要执行...,当前引用计数:%d",[self retainCount]);
    [super dealloc];
}
@end

代码很简单,除了"构造函数"跟"析构函数"之外,没有任何其它多余处理。

主程序调用

#import <Foundation/Foundation.h>
#import "Sample.h"
  
int main (int argc, const char * argv[]) {  
      
    Sample *_sample = [Sample new]; //构造函数被调用了!当前引用计数:1
    NSLog(@"_sample.retainCount=%d",[_sample retainCount]);//1  
      
    [_sample retain];
    NSLog(@"_sample.retainCount=%d",[_sample retainCount]);//2
      
    [_sample retain];
    NSLog(@"_sample.retainCount=%d",[_sample retainCount]);//3  
      
    [_sample release];
    NSLog(@"_sample.retainCount=%d",[_sample retainCount]);//2
      
    [_sample release];
    NSLog(@"_sample.retainCount=%d",[_sample retainCount]);//1
      
    [_sample release];//析构函数将要执行...,当前引用计数:1
    NSLog(@"_sample.retainCount=%d",[_sample retainCount]);//1,注:即便是在析构函数执行后,如果立即再次引用对象的retainCount,仍然返回1,但以后不管再试图引用该对象的任何属性或方法,都将报错
    NSLog(@"_sample.retainCount=%d",[_sample retainCount]);//对象被释放之后,如果再尝试引用该对象的任何其它方法,则报错
    //[_sample retain];//同上,会报错 
       
    return 0;   
}

这段代码主要验证:对象刚创建时retainCount是否为1,以及retain和release是否可以改变retainCount的值,同时retainCount减到0时,是否会自动执行dealloc函数

nil 的问题:

1.1 如果仅声明一个Sample类型的变量(其实就是一个指针),而不实例化,其初始值为nil

1.2 变量实例化以后,就算release掉,dealloc被成功调用,其retainCount并不马上回到0(还能立即调用一次且仅一次[xxx retainCount]),而且指针变量本身也不会自动归为nil值

1.3 dealloc被调用后,必须手动赋值nil,retainCount才会自动归0

以上结论是实际试验得出来的,见下面的代码:

Sample *s ; 
NSLog(@"s %@,retainCount=%d",s==nil?@"is nil":@"is not nil",[s retainCount]);//s is nil,retainCount=0   
s = [Sample new];
NSLog(@"s %@,retainCount=%d",s==nil?@"is nil":@"is not nil",[s retainCount]);//s is not nil,retainCount=1   
[s release];
NSLog(@"s %@,retainCount=%d",s==nil?@"is nil":@"is not nil",[s retainCount]);//s is not nil,retainCount=1
//NSLog(@"s %@,retainCount=%d",s==nil?@"is nil":@"is not nil",[s retainCount]);//报错:Program received signal:  “EXC_BAD_ACCESS”.
s = nil;
NSLog(@"s %@,retainCount=%d",s==nil?@"is nil":@"is not nil",[s retainCount]);//s is nil,retainCount=0

所以千万别用if (x == nil) 或 if ([x retainCount]==0)来判断对象是否被销毁,除非你每次销毁对象后,手动显式将其赋值为nil

2、复杂情况

上面的示例过于简章,只有一个类自己独耍,如果有多个类,且相互之间有联系时,情况要复杂一些。下面我们设计二个类Shoe和Man(即“鞋子类”和”人“),每个人都要穿鞋,所以Man与Shoe之间应该是Man拥有Shoe的关系。

Shoe.h接口定义部分

#import <Foundation/Foundation.h>
  
  
@interface Shoe : NSObject {
    NSString* _shoeColor;
    int _shoeSize;
}
  
//鞋子尺寸
-(void) setSize:(int) size;
-(int) Size;
  
//鞋子颜色
-(void) setColor:(NSString*) color;
-(NSString*) Color;
  
//设置鞋子的颜色和尺码
-(void) setColorAndSize:(NSString*) pColor shoeSize:(int) pSize;
  
@end

Shoe.m实现部分

//
//  Shoe.m
//  MemoryManage_1
//
//  Created by jimmy.yang on 11-2-19.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//
  
#import "Shoe.h"
  
  
@implementation Shoe
  
//构造函数
-(id)init
{
    if (self=[super init]){
        _shoeColor = @"black";
        _shoeSize = 35;
    }
    NSLog(@"一双 %@ %d码 的鞋子造好了!",_shoeColor,_shoeSize);
    return (self);
}
  
-(void) setColor:(NSString *) newColor
{
    _shoeColor = newColor;
}
  
-(NSString*) Color
{
    return _shoeColor;
}
  
-(void) setSize:(int) newSize
{
    _shoeSize = newSize;
}   
  
-(int) Size
{
    return _shoeSize;
}
  
-(void) setColorAndSize:(NSString *)color shoeSize:(int)size
{
    [self setColor:color];
    [self setSize:size];
}
  
  
//析构函数
-(void) dealloc
{
    NSLog(@"%@ %d码的鞋子正在被人道毁灭!",_shoeColor,_shoeSize);
    [super dealloc];
}
  
  
@end

Man.h定义部分

//
//  Man.h
//  MemoryManage_1
//
//  Created by jimmy.yang on 11-2-20.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//
  
#import <Foundation/Foundation.h>
#import "Shoe.h"
  
  
@interface Man : NSObject {
    NSString *_name;
    Shoe *_shoe;
}
  
  
-(void) setName:(NSString*) name;
-(NSString*)Name;
  
-(void) wearShoe:(Shoe*) shoe;
@end

Man.m实现部分

//
//  Man.m
//  MemoryManage_1
//
//  Created by jimmy.yang on 11-2-20.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//
  
#import "Man.h"
  
  
@implementation Man
  
//构造函数
-(id)init
{
    if (self=[super init]){
        _name = @"no name";
    }
    NSLog(@"新人\"%@\"出生了!",_name);
    return (self);
}
  
  
-(void) setName:(NSString *)newName
{
    _name =newName;
}
  
-(NSString*)Name
{
    return _name;
}
  
-(void) wearShoe:(Shoe *)shoe
{
    _shoe = shoe;
}
  
//析构函数
-(void) dealloc
{
    NSLog(@"\"%@\"要死了! ",_name);
    [super dealloc];
}
      
@end

main函数调用

#import <Foundation/Foundation.h>
#import "Shoe.h"
#import "Man.h"
  
int main (int argc, const char * argv[]) {  
      
    Man *jimmy = [Man new];
    [jimmy setName:@"Jimmy"];
      
      
    Shoe *black40 =[Shoe new];
    [black40 setColorAndSize:@"Black" shoeSize:40];
      
    [jimmy wearShoe:black40];
      
    [jimmy release];
    [black40 release];
      
    return 0;
      
}

2011-02-23 13:05:50.550 MemoryManage[253:a0f] 新人"no name"出生了!
2011-02-23 13:05:50.560 MemoryManage[253:a0f] 一双 black 35码 的鞋子造好了!
2011-02-23 13:05:50.634 MemoryManage[253:a0f] "Jimmy"要死了!
2011-02-23 13:05:50.636 MemoryManage[253:a0f] Black 40码的鞋子正在被人道毁灭!

以上是输出结果,一切正常,jimmy与black40占用的资源最终都得到了释放。但是有一点不太合理,既然鞋子(black40)是属于人(jimmy)的,为什么人死了(即:[jimmy release]),却还要main函数来责任烧掉他的鞋子?(即:main函数中还是单独写一行[black40 release]) 貌似人死的时候,就连带自上的所有东西一并带走,这样更方便吧。

ok,我们来改造一下Man.m中的dealloc()方法,改成下面这样:

//析构函数
-(void) dealloc
{
    NSLog(@"\"%@\"要死了! ",_name);
    [_shoe release];//这里释放_shoe
    [super dealloc];
}

即:在Man被销毁的时候,先把_shoe给销毁。这样在main()函数中,就不再需要单独写一行[black40 release]来释放black40了.

现在又有新情况了:jimmy交了一个好朋友mike,二人成了铁哥们,然后jimmy决定把自己的鞋子black40,跟mike共同拥有,于是main函数就成了下面这样:

int main (int argc, const char * argv[]) {  
      
    Man *jimmy = [Man new];
    [jimmy setName:@"Jimmy"];   
      
    Shoe *black40 =[Shoe new];
    [black40 setColorAndSize:@"Black" shoeSize:40];
      
    [jimmy wearShoe:black40];
      
    Man *mike = [Man new];
    [mike setName:@"mike"];
    [mike wearShoe:black40];//mike跟jimmy,现在共同拥有一双40码黑色的鞋子
      
    [jimmy release];
    [mike release]; 
      
    return 0;
}

麻烦来了:jimmy在挂掉的时候(即[jimmy release]这一行),已经顺手把自己的鞋子也给销毁了(也许他忘记了mike也在穿它),然后mike在死的时候,准备烧掉自已的鞋子black40,却被告之该对象已经不存在了。于是程序运行报错:

Running…
2011-02-23 13:38:53.169 MemoryManage[374:a0f] 新人"no name"出生了!
2011-02-23 13:38:53.176 MemoryManage[374:a0f] 一双 black 35码 的鞋子造好了!
2011-02-23 13:38:53.177 MemoryManage[374:a0f] 新人"no name"出生了!
2011-02-23 13:38:53.179 MemoryManage[374:a0f] "Jimmy"要死了!
2011-02-23 13:38:53.181 MemoryManage[374:a0f] Black 40码的鞋子正在被人道毁灭!
2011-02-23 13:38:53.183 MemoryManage[374:a0f] "mike"要死了!
Program received signal:  “EXC_BAD_ACCESS”.
sharedlibrary apply-load-rules all
(gdb)

上面红色的部分表示程序出错了:Bad_Access也就是说访问不存在的地址。

最解决的办法莫过于又回到原点,Man.m的dealloc中不连带释放Shoe实例,然后把共用的鞋子放到main函数中,等所有人都挂掉后,最后再销毁Shoe实例,但是估计main()函数会有意见了:你们二个都死了,还要来麻烦我料理后事。

举这个例子无非就是得出这样一个原则:对于new出来的对象,使用retain造成的影响一定要运用相应的release抵消掉,反之亦然,否则,要么对象不会被销毁,要么过早销毁导致后面的非法引用而出错。

 

本文摘自:http://www.cnblogs.com/yjmyzz/archive/2011/02/23/1958961.html

 


    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3