转向ARC的说明——翻译Apple官方文档

ARC是一个编译器特征,它提供了对OC对象自动管理内存。ARC让开发者专注于感兴趣的代码和对象的关系,而不用考虑对象的retain和release。

原文地址

概要

ARC在编译时期添加代码,保证对象可用。概念上说,ARC遵循手动引用计数的规则,替开发者在编译时期添加合适的代码。

Xcode4.2(Mac OS 10.6、10.7和iOS4和iOS5)支持ARC,弱引用在10.6和iOS4上不支持。

Xcode提供了一个工具:自动机械得转化为ARC(比如移除retain和release的调用),并帮助开发者解决不能自动迁移的问题。迁移工具将所有文件转化成ARC,开发者也可以对单个文件实施ARC,方便于开发者对某些文件手动引用计数。

ARC概要

ARC评估了对象的生命周期,并自动插入合适的代码在编译时期,从而代替开发者不得不考虑何时需要retain、release和autolease的问题。编译器替开发者,生成合适的dealloc方法。一般来说,当开发者需要在手动引用计数和ARC配合使用时候,使用传统ARC的Cocoa命名惯例是很重要的。

一个正确的完整的Person类如下:

[objc] view plain copy

  1. @interface Person : NSObject
  2. @property NSString *firstName;
  3. @property NSString *lastName;
  4. @property NSNumber *yearOfBirth;
  5. @property Person *spouse;
  6. @end
  7. @implementation Person
  8. @end

对象的属性默认是strong;strong属性在 “ARC
Introduces New Lifetime Qualifiers.”
有描述

[objc] view plain copy

  1. - (void)contrived {
  2. Person *aPerson = [[Person alloc] init];
  3. [aPerson setFirstName:@"William"];
  4. [aPerson setLastName:@"Dudney"];
  5. [aPerson setYearOfBirth:[[NSNumber alloc] initWithInteger:2011]];
  6. NSLog(@"aPerson: %@", aPerson);
  7. }

ARC掌管了内存管理,所以Person和NSNumber不会泄露。

开发者还可以安全得实现Person类的方法takeLastNameFrom:

[objc] view plain copy

  1. - (void)takeLastNameFrom:(Person *)person {
  2. NSString *oldLastname = [self lastName];
  3. [self setLastName:[person lastName]];
  4. NSLog(@"Lastname changed from %@ to %@", oldLastname, [self lastName]);
  5. }

ARC确保oldLastName在NSLog之前不会被销毁。

ARC 强制执行了新的规则

ARC执行了一些新的规则,是其他编译模式没有的。这个规则是:致力于提供一个安全可靠的内存管理模式。在某些情况下,他们只是执行最佳实践;某些情况,他们简化你的代码或者处理那没明显的不需要内存问题。如果你违反这些规则,立即得到一个编译错误,而不会在运行显示一个微妙的bug。

● 开发者不能显示调用dealloc;不能实现和调用retain、release、retainCount和autorelease。

禁止使用@selector(retain),@selector(release)等等。

开发者仍可以实现dealloc方法,如果你想管理资源而不是变量。开发者不能release变量,但是可以调用[systemClassInstance setDelegate:nil]在系统类上,或者其他不是用ARC编译的代码上。

ARC中自定义的dealloc方法,不需要调用[super dealloc](其实这样做就会导致编译错误),编译器会强制自动链接到父类。

开发者仍可以对Core Foundation-style对象,使用CFRetain,CFRelease和其他相关方法。

● 不能使用NSAllocateObject或者NSDeallocateObject。开发者创建对象使用alloc,运行时环境负责销毁对象。

● 在C数据结构中,不能使用对象指针。可以使用OC类来代替C的struct

● id和void*没有自动转换.

开发者必须使用特殊的类型转化.开发者需要通过函数参数传递,在OC对象和Core Foundation之间做类型转换。

● 开发者不能使用NSAutoreleasePool对象。ARC下使用@autoreleasepool,它比NSAtuoreleasePool更有效率。

● 开发者不能使用内存zones。不用再使用NSZone了。他们已经被现代的OC运行环境给忽略了。

为了配合手动引用计数,ARC的方法命名有限制:

● 访问器方法不能已new开头,反过来就是:开发者不能声明一个已new开头的属性,除非你给你指定一个getter

[objc] view plain copy

  1. // 不正确:
  2. @property NSString *newTitle;
  3. // 正确:
  4. @property (getter=theNewTitle) NSString *newTitle;

ARC引入了新的Lifetime修饰符。

ARC引入几个新的修饰符和弱(weak)引用。弱引用不会延伸到对象生命周期,并自动设置为nil,当该对象没有任何的强引用的时候。开发者需要使用这些修饰来管理对象图。通常ARC不对循环引用做警告。谨慎得使用弱引用可以保证不会循环引用。

Property属性

weak和strong关键字作为新的property属性被引入,例如:

[objc] view plain copy

  1. // The following declaration is a synonym for: @property(retain) MyClass *myObject;
  2. @property(strong) MyClass *myObject;
  3. // The following declaration is similar to "@property(assign) MyClass *myObject;"
  4. // except that if the MyClass instance is deallocated,
  5. // the property value is set to nil instead of remaining as a dangling pointer.
  6. @property(weak) MyClass *myObject;

ARC下,strong是默认property属性

变量的修饰符

开发者使用下面得lifetime修饰。

__strong

__weak

__unsafe_unretained

__autoreleasing

● 默认是__strong。只要对象还有强引用,该对象“活着”。

● __weak不保留对象,只是简单引用。weak对象将被设置nil,当对象没有任何强引用的时候。

● __unsafe_unretained 不保留对象,只是简单引用。但是不设置为nil,当对象没有任何强引用得时候。如果对象被销毁,__unsafe_unretained的对象将会野指针。

● __autoreleasing 用于标识id*的引用参数,或者需要自动释放的返回的对象。

开发者需要正确修饰变量。使用下面的格式来修饰变量声明。

类名*  修饰  变量名

例如:

[objc] view plain copy

  1. MyClass * __weak myWeakReference;
  2. MyClass * __unsafe_unretained myUnsafeReference;

其他的变种在技术上是不正确的,但可能可以通过编译。了解更多http://cdecl.org/

在栈上小心使用__weak。考虑下面的代码:

[objc] view plain copy

  1. NSString * __weak string = [[NSString alloc] initWithFormat:@"First Name: %@", [self firstName]];
  2. NSLog(@"string: %@", string);

尽管string在初始化后被使用了。但是,由于在赋值的时候没有强引用;因此它将立即被销毁。

● 开发者同样需要注意传递引用的地方,例如下面的代码:

[objc] view plain copy

  1. NSError *error;
  2. BOOL OK = [myObject performOperationWithError:&error];
  3. if (!OK) {
  4. // Report the error.
  5. // ...

然而,这种错误是隐含的。

[objc] view plain copy

  1. NSError * __strong e;

并且声明的方法可能是下面这样(参数是__autoreleasing的):

[objc] view plain copy

  1. -(BOOL)performOperationWithError:(NSError * __autoreleasing *)error;

那么,编译器将重写代码:

[objc] view plain copy

  1. NSError * __strong error;
  2. NSError * __autoreleasing tmp = error;
  3. BOOL OK = [myObject performOperationWithError:&tmp];
  4. error = tmp;
  5. if (!OK) {
  6. // Report the error.
  7. // ...

本地变量声明(__strong)和参数(__autoreleasing)导致编译器创建临时变量。当开发者对__strong对象取地址,将参数声明为id __strong*,就得到原始的指针。或者开发者可以将变量声明为__autoreleasing

使用Lifetime修饰符,避免循环引用

开发者可以通过lifetime修饰符来避免循环引用。例如,如果你有一个对象图(关于父-子继承)。并且父类需要引用子类,相反子类也要用。这时候,开发者把parent-to-child写做strong并把child-to-parent关系写作weak。其他情况可能有些麻烦,特别是调用block变量的时候。

手动引用计数模式下,__block id x 这样的写法(x是一个对象),不会对x进行retain。在ARC模式,__block id x;默认retain x(就像其他变量一样)。如果想在ARC模式下,得到手动引用计数的效果,开发者可以使用__unsafe_unretained __block id x。顾名思义,__unsafe_unretained __block id x是危险的(因为他可能导致野指针)因此也不建议使用。好的解决方案是:使用__weak或者将__block的值设置为nil,来打断retain循环。

下面的代码段展示了如何使用手动引用计数

[objc] view plain copy

  1. MyViewController *myController = [[MyViewController alloc] init…];
  2. // ...
  3. myController.completionHandler =  ^(NSInteger result) {
  4. [myController dismissViewControllerAnimated:YES completion:nil];
  5. };
  6. [self presentViewController:myController animated:YES completion:^{
  7. [myController release];
  8. }];

正如说的那样,开发者可以使用__block修饰符并且设置myController变量为nil,在完成处理的时候。(这种方法不推荐,不是每一个程序员都会完整的将mycontroller置为nil的)

[objc] view plain copy

  1. MyViewController * __block myController = [[MyViewController alloc] init…];
  2. // ...
  3. myController.completionHandler =  ^(NSInteger result) {
  4. [myController dismissViewControllerAnimated:YES completion:nil];
  5. myController = nil;
  6. };

或者,你可以使用临时的__weak变量。下面是一个简单的实现(推荐)

[objc] view plain copy

  1. MyViewController *myController = [[MyViewController alloc] init…];
  2. // ...
  3. MyViewController * __weak weakMyViewController = myController;
  4. myController.completionHandler =  ^(NSInteger result) {
  5. [weakMyViewController dismissViewControllerAnimated:YES completion:nil];
  6. };

对于non-trivial循环,开发者应该使用下面代码:

[objc] view plain copy

  1. MyViewController *myController = [[MyViewController alloc] init…];
  2. // ...
  3. MyViewController * __weak weakMyController = myController;
  4. myController.completionHandler =  ^(NSInteger result) {
  5. MyViewController *strongMyController = weakMyController;
  6. if (strongMyController) {
  7. // ...
  8. [strongMyController dismissViewControllerAnimated:YES completion:nil];
  9. // ...
  10. }
  11. else {
  12. // Probably nothing...
  13. }
  14. };

在某些情况,开发者使用__unsafe_unretained,如果类本身不是__weak修饰。然而,这样将变得不切合实际了,因为它可能很难或者不可能去验证:__unsafe_unretained的指针仍然可用并且指向某些变量。

ARC使用一个新语句管理Autorelease Pools

使用ARC,开发者不能直接使用NSAutoreleasePool来管理autorelease pools。而使用@autoreleasepool代替它。

[objc] view plain copy

  1. @autoreleasepool {
  2. // Code, such as a loop that creates a large number of temporary objects.
  3. }

这个简单的结构允许编译器思考引用计数的状态。进入的时候,自动释放池被push。在正常退出的时候自动释放池配poped出来。为了配合现有代码,如果代码异常退出,自动释放池将不会pop出来。它比NSAutoreleasePool更有效率;因此建议开发者替换NSAtuoreleasePool。

Patterns for Managing Outlets Become Consistent Across Platforms(略)

栈变量被初始化为nil

使用ARC,strong、weak和autoreleasing栈变量将隐式初始化为nil,例如:

[objc] view plain copy

  1. - (void)myMethod {
  2. NSString *name;
  3. NSLog(@"name: %@", name);
  4. }

将打印出null,而不是崩溃。

使用编译器选项来开启和关闭ARC

开发者使用-fobjc-arc 编译选项开启ARC,还可以对某一个文件使用ARC,便于在使用手动引用计数的文件中使用ARC。对于已经使用ARC的工程,仍可以指定一个文件来关闭ARC通过-fno-objc-arc编译选项。

管理Toll-Free Bridging

在多数的Cocoa程序中,开发者需要使用Core Foundaton-style对象,无论是从Core Foundation框架还是从Core foundation的其他框架比如Core Graphics。

编译器不会自动管理Core foundation对象的生命周期。开发者必须根据COreFoundation的内存管理规则,使用CFRetain和CFRelease。

如果开发者在OC和Core foundation两种对象做转换,需要告诉编译器对象的所有权。

● __bridge 不改变所有权的情况下,将OC和Core foundaton对象之间转换。

● __bridge_retained 或者 CFBridgingRetain 或者对象的所有权,将OC和Corefoundaton对象之间转换。开发者仍有责任将释放对象通过CFRelease。

● __bridge_transfer 或者CFBridgingRelease将一个非OC指针,转化为OC指针,ARC负责释放对象,对象(内存)的管理权交给ARC。

例如,现有代码:

[objc] view plain copy

  1. - (void)logFirstNameOfPerson:(ABRecordRef)person {
  2. NSString *name = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
  3. NSLog(@"Person‘s first name: %@", name);
  4. [name release];
  5. }

开发用下面的代码代替

[objc] view plain copy

  1. - (void)logFirstNameOfPerson:(ABRecordRef)person {
  2. NSString *name = (NSString *)CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
  3. NSLog(@"Person‘s first name: %@", name);
  4. }

编译器处理从Cocoa方法返回的 CF 对象

编译器知道返回Core foundaion类的OC的方法,遵循历史的规定。例如,编译器知道从CGColor方法返回的GCColor是不拥有的。开发者必须使用合适的类型去转化。例如:

[objc] view plain copy

  1. NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]];
  2. [colors addObject:(id)[[UIColor lightGrayColor] CGColor]];

使用所有权关键字转化函数参数

当开发者在OC和Core foundation的对象之间转化时,需要告诉编译器传递object的所有权。Core foundation对象所有权的规则在CoreFoundation的内存管理规则中。OC的所有权规则在Advanced Memory Management Programming Guide中。

下面的代码段,数组传递给CGGradientCreateWithCorlors函数需要一个合适的转化。数组是arrayWitshObjects返回的,所以,不要将所有权传递给函数,因此使用__bridge

[objc] view plain copy

  1. NSArray *colors = <#An array of colors#>;
  2. CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations);

下面代码段实现了一个context,使用Core Foundation内存管理的方法。

[objc] view plain copy

  1. - (void)drawRect:(CGRect)rect {
  2. CGContextRef ctx = UIGraphicsGetCurrentContext();
  3. CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
  4. CGFloat locations[2] = {0.0, 1.0};
  5. NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]];
  6. [colors addObject:(id)[[UIColor lightGrayColor] CGColor]];
  7. CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations);
  8. CGColorSpaceRelease(colorSpace);  // Release owned Core Foundation object.
  9. CGPoint startPoint = CGPointMake(0.0, 0.0);
  10. CGPoint endPoint = CGPointMake(CGRectGetMaxX(self.bounds), CGRectGetMaxY(self.bounds));
  11. CGContextDrawLinearGradient(ctx, gradient, startPoint, endPoint,
  12. kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
  13. CGGradientRelease(gradient);  // Release owned Core Foundation object.
  14. }

将工程转化为ARC,遇到的常见问题

当迁移现有的项目,你可能会遇到的各种问题。这里有一些共同的问题,共同解决方案。

● 不能调用retain,release或者autorelease,这是一种特性,甚至可以这么写:

[objc] view plain copy

  1. while ([x retainCount]) { [x release]; }

● 不能调用dealloc

通常,开发者在单例的实现或者替换一个对象的init方法的时候调用dealloc。对于单例模式,使用共享实例模式。在init方法中,你不用调用dealloc,因为对象会被释放,当重写self的时候。

● 不能使用NSAutoreleasePool对象

是哟表格@autoreleasepool{}代替NSAutoreleasePool.这将强制一个block处于一个自动释放池中。它比NSAutoreleaePool快6倍。@autoreleasepool也在在非ARC模式下工作。

● ARC需要开发者对[super init]赋值给self在init方法中。

下面代码是不可行的

[objc] view plain copy

  1. [super init];

简单的修正是:

[objc] view plain copy

  1. self = [super init];

根号的修复是这样的

[objc] view plain copy

  1. self = [super init];
  2. if (self) {
  3. ...

● 不能实现retain和release方法。

实现自定义的retain和release方法打破弱指针。提供了几个常用的 “实现自定义”的原因。

1.性能

不要这么做,NSObject的retain和release已经很快了。如果你发现仍有问题,请提出这个bug

2.实现一个自定义的弱指针系统

使用__weak代替

3.实现单例

使用shared instance pattern代替。或者使用类来代替方法,避免分配对象。

● assigned 将变成strong

在ARC之前,变量的assigned的不会延伸到对象的生命周期。为了让property变成强引用,开发者通常实例化或者synthesized访问器方法,里面是内存管理方法。相比之下,你可以这样实现访问器方法:

[objc] view plain copy

  1. @interface MyClass : Superclass {
  2. id thing; // Weak reference.
  3. }
  4. // ...
  5. @end
  6. @implementation MyClass
  7. - (id)thing {
  8. return thing;
  9. }
  10. - (void)setThing:(id)newThing {
  11. thing = newThing;
  12. }
  13. // ...
  14. @end

ARC下,实例中的变量默认是strong引用,assigning一个对象给实例中的变量延伸到对象的生命周期。迁移工具不能决定一个实例变量即将weak。保持相同的行为之前,你必须标记实例变量是weak,或声明它的property

[objc] view plain copy

  1. @interface MyClass : Superclass {
  2. id __weak thing;
  3. }
  4. // ...
  5. @end
  6. @implementation MyClass
  7. - (id)thing {
  8. return thing;
  9. }
  10. - (void)setThing:(id)newThing {
  11. thing = newThing;
  12. }
  13. // ...
  14. @end

或者

[objc] view plain copy

  1. @interface MyClass : Superclass
  2. @property (weak) id thing;
  3. // ...
  4. @end
  5. @implementation MyClass
  6. @synthesize thing;
  7. // ...
  8. @end

● 不能使用strong ids在c的数据结构

例如,下面的c结构将不能编译过

[objc] view plain copy

  1. struct X { id x; float y; };

这是因为x默认是strong retain,但是,在正常运行情况下,编译器不能安全的合成所有需要的代码。比如:如果你传递一个指针给x或者y后,执行了free,每一个id将被release掉,在struct被free之前。编译器不能可靠的做这些。所以strong ids在结构,在ARC中完全不允许。下面是一些解决方案:

1.用OC类代替c结构。这应该是最好的解决办法。

2.如果使用OC类是次要的方法(可能你想要一个高密度的结构数组),那么考虑使用void*代替。这需要使用显示的转化。

3.把对象引用作为__unsafe_unretained。这种方法是半常见的模式,这样是有用的。

[objc] view plain copy

  1. struct x { NSString *S;  int X; } StaticArray[] = {
  2. @"foo", 42,
  3. @"bar, 97,
  4. ...
  5. };

开发者这样声明

[objc] view plain copy

  1. struct x { NSString * __unsafe_unretained S; int X; }

这可能是有问题的,如果对象可以被释放时指针是不安全的,但它是非常有用的东西,被称为是字符串常量。

● 不能直接将id和void*进行转化(包含Core Foundation类型)参考Managing Toll-Free Bridging

经常遇到的问题

我该怎样认识ARC?它在哪儿放置retains/releases。

不要想什么地方调用retain/release,考虑程序本身算法吧。考虑"strong and weak"关系,对象的所有权关系和可能存在的循环引用。

我还需要写dealloc方法么

可能需要。因为ARC不会自动对 Core Foundation 对象,文件描述符等等进行malloc/free,,这些资源扔需要写dealloc方法。

不不能release对象的变量,但是可以调用[self setDelegate:nil]在系统的类和其他不用ARC的代码。

ARC种 不需要dealloc方法,或者[super dealloc];在运行时系统调用super代码。

在ARC种,仍存在循环引用?

是的。ARC自动retain/release并可能继承了循环引用的问题。幸运的是:迁移到ARC的代码很少泄露,因为无论properties是不是retain的,都被被声明为retain了。

在ARC种blocks是如何工作的

Block能正常工作,当你在栈上传递的时候,比如作为返回值。你无需block copy了。当你传递block在栈下面的时候,添加到arrayWithObjects等需要retain的地方,需要使用[^{ }copy]。

有一件事情需要清除:NSString *__block myString是retain在ARC模式种,不可能是野指针。为了得到以前的行为,使用__block NSString *__unsafe_unretained myString 或者使用__block NSString *__weak myString.

我可以在雪豹OS种开发中使用ARC么?

不行。雪豹版本的Xcode4.2不支持ARC。

ARC下,可以创建C语言的retain的指针数组么

可以

[objc] view plain copy

  1. // Note calloc() to get zero-filled memory.
  2. __strong SomeClass **dynamicArray = (__strong SomeClass **)calloc(entries, sizeof(SomeClass *));
  3. for (int i = 0; i < entries; i++) {
  4. dynamicArray[i] = [[SomeClass alloc] init];
  5. }
  6. // When you‘re done, set each entry to nil to tell ARC to release the object.
  7. for (int i = 0; i < entries; i++) {
  8. dynamicArray[i] = nil;
  9. }
  10. free(dynamicArray);

下面是一些注意的地方:

● 你要写__strong SomeClass **在某些情况,默认情况是__autoreleasing SomeClass **.

● 开辟的内存必须是零填充

● 需要设置每一项为nil在释放array的时候(memset和bzero不好使的)

ARC慢么?

取决于你怎么测量,通常是不慢。编译器消除很多无关紧要的retain/release调用。投入很大的努力在加快OC下的运行环境。尤其是返回一个retian/autoreleased对象,ARC并不是真正将它放到自动释放池。

有一件事需要清除:优化器不在debug模式下。所以想看到更多的retain/release的调用,使用-O0比-Os

ARC在ObjC++模式下工作么

是的,甚至可以将strong/weakids在类和容器中。ARC编译器合成retain/release逻辑在拷贝构造函数和析构函数钟。

那些类不支持weak引用

下面的类不能创建弱引用:

NSATSTypesetter, NSColorSpace, NSFont, NSMenuView, NSParagraphStyle, NSSimpleHorizontalTypesetter, and NSTextView.

对于声明properties时,你应该使用retain代替weak。对于变量你应该使用__unsafe_unretained代替__weak.另外,你不能创建这些类的弱引用:NSHashTable, NSMapTable, or NSPointerArray

对NSCell和其他类使用NSCopyObject时候。

没什么特别的。ARC负责的显示retain的场景。ARC模式下,所有的copy方法应该仅仅copy实例变量。

我可以对某个文件不使用ARC么?

是的。当开发者迁移工程到ARC时,对所有OC源文件设置为-fobjc-arc编译选项。开发者可以指定一个文件设置-fno-objc-arc编译选项。

GC(Grabage Collection)在mac上过时了?

Grabage Collection在10.8上已经过时,将来会重OS X中移除。ARC将是收推荐的替代技术。为了帮助迁移现有程序,ARC迁移工具在Xcode >=4.3 支持将GC迁移到ARC。

点击打开原文

时间: 2024-08-03 18:57:13

转向ARC的说明——翻译Apple官方文档的相关文章

自己翻译 delegation 官方文档

什么是代理,知道怎么用,见过N次.会用代理传值,还不够.代理到底是用来干嘛的嘛?还是看看官方文档吧,自己翻译出来看看是不是通顺 代理: 代理是一个简单高效的模式,尤其是一个类在编程的过程中代表或者需要和另一个类协调的时候.委托对象(委托方)会持有代理对象(代理方)的一个引用,并在合适的时机给代理方发送一个消息.这个消息通知代理方,委托方将要处理一个件事或者刚处理完一件事.代理方可能会对这个消息做出相应,如更新自己或者其他类的界面或状态,并且在一些情况下,代理方可以返回一个值,来影响一个即将被处理

【Android官方文档】翻译Android官方文档-Activities(一)

Activity是可以给用户提供交互操作的程序组件,例如打电话,拍照,发送邮件,抑或者是显示地图.通常窗口会填满屏幕,但是也可以做到比屏幕小或者是悬浮在窗口顶部. App通常由多个Activities组成,它们之间支持相互跳转.一般情况下,每个Activity在应用中都是特别的,就好像 主Activity一样,主activity是应用第一个Activity,其他Activity可以通过其他操作启动.一个新的Activity的启动,那么旧Activity就会被停止,但是系统会保存这些activit

IT忍者神龟之Struts2-Json-Plugin 的使用(翻译自官方文档)

在 Struts2 中要使用 Ajax 获得 Json 数据我认为目前还是 struts2-json-plugin 了.当然你你可以用手工用像 XStream.Google Gson.Jackson 这样的工具手工把 Java 对象转换成 Json 字符串再写往 Response 去,要写的代码自然多不了,还得留心字符集与 content type.而 struts2-json-plugin 毫无疑问是与 Struts2 最亲近了,只需你配置一些属性就能得到你想的结果. 本想分几篇逐步介绍如何使

Android官方文档系列(翻译)

下面一些内容是我翻译Android官方文档相关文章. 菜鸟上路,一边学习一边整理,若您发现有错误的地方还请不吝赐教. Activity 解读Android之Activity基础知识 解读Android之任务和Back栈 Service 解读Android之Service(1)基础知识 解读Android之Service(2)Bound Service 解读Android之Service(3)AIDL ContentProvider 解读Android之ContentProvider(1)CRUD

Android官方文档之App Components(Loaders)

Loaders在Android 3.0中引入.在Activity和Fragment中,使用Loaders可以方便地加载数据.有关Activity和Fragment的介绍,您可以参考我翻译的官方文档: <Activities> <Fragments> 本文将介绍Loaders API.Loaders的启动.重启.Loaders管理器 等内容,如需访问Loaders的官方原文,您可以点击这个链接:<Loaders>. Loaders Loaders具有如下特性: 它适用于任

Android官方文档之App Components(Common Intents)

Intent的真正强大之处在于它的隐式Intent,隐式Intent需要配合Intent-filters使用,有关这方面的概念和知识,您可以参考我翻译的官方文档:<Android官方文档之App Components(Intents and Intent Filters)>. 隐式Intent足够强大,以至于系统提供了大量的Intent方便开发者启动系统应用程序,本文将介绍一些常用的隐式Intent.以及如何自定义intent-filters以匹配隐式intent. 如需阅读官方原文,您可以点

Android官方文档之Creating a Content Provider

写在前面的话:说两点.1.很荣幸自己的两篇文章< Android官方文档之App Components(Intents and Intent Filters)>.<Android官方文档之App Components(Common Intents)>被郭霖老师转载了,一方面说明我的博客内容得到了认可,另一方面也鞭策我继续写出质量更高的博文:2.最近在翻译官方文档,今天翻墙一看,发现页面改版了,而且居然默认显示了中文的文档(其实改版以前也有官方的中文文档,只是默认显示英文而已,另外中

Android官方文档之Bound Services

绑定式Service在CS结构中扮演着Server的角色.绑定式Service允许其他组件(如Activity)绑定该Service.发送请求.接收响应.甚至IPC通信( interprocess communication).绑定式Service通常服务于其他应用程序的组件.且没有明确的后台的概念(does not run in the background indefinitely). 本文将介绍bound Service的相关内容,包括其创建.与其他应用组件如何绑定 等.有关Service

Android官方文档之App Components(Common Intents)(转载)

原文地址:http://blog.csdn.net/vanpersie_9987/article/details/51244558#rd Intent的真正强大之处在于它的隐式Intent,隐式Intent需要配合Intent-filters使用,有关这方面的概念和知识,您可以参考我翻译的官方文档:<Android官方文档之App Components(Intents and Intent Filters)>. 隐式Intent足够强大,以至于系统提供了大量的Intent方便开发者启动系统应用