RESTful 概念 REpresentational State Transfer 表征性状态传输
复用 HTTP 本身的协议定义
带来的好处:通用,动词,code,缓存,安全
例子
1 2 3 4 5 6
BAD /getProduct /addProduct /deleteProduct /listProducts /productShop?productId=1
对单一实体的重复
多个实体对操作的重复
实体之间逻辑接口的重复定义
1 2 3 4 5 6 7 8 9 10 11
GOOD GET /products : will return the list of all products GET /products/4 : will retrieve product #4 POST /products : will add a product to the collection PUT /products/4 : will update product #4 DELETE /products/4 : will delete product #4
GET /products/4/shop GET /users/3/favorite_schools POST /users/3/favorite_schools PUT /users/3/favorite_schools/5
// Response handlers can even be chained: Alamofire.request(.GET, "http://httpbin.org/get") .responseString { _, _, string, _ in println(string) } .responseJSON { _, _, JSON, _ in println(JSON) }
URL / JSON / plist Parameter Encoding 除了以上几种 还可以自定义 Alamofire provides built-in response serialization for strings, JSON, and property lists, but others can be added in extensions on Alamofire.Request.
Upload File / Data / Stream / MultipartFormData 多种文件上传方式
Download using Request or Resume data
Authentication with NSURLCredential
HTTP Response Validation
Progress Closure & NSProgress
cURL Debug Output
Comprehensive Unit Test Coverage
某些点
url编码 GET
1 2 3
GET Request With URL-Encoded Parameters Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"]) // http://httpbin.org/get?foo=bar
Automatically validates status code within 200...299 range, and that the Content-Type header of the response matches the Accept header of the request, if one is provided.
let request = Alamofire.request(.GET, "http://httpbin.org/ip")
println(request)
// GET http://httpbin.org/ip (200)
DebugPrintable
1 2 3
let request = Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
debugPrintln(request)
支持暂停/恢复/取消
suspend(): Suspends the underlying task and dispatch queue
resume(): Resumes the underlying task and dispatch queue. If the owning manager does not have startRequestsImmediately set to true, the request must call resume() in order to start.
cancel(): Cancels the underlying task, producing an error that is passed to any registered response handlers.
/** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. */ public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; m.flags = 0; // clear in-use flag sPoolSize--; return m; } } return new Message(); }
从代码片中,可以看到Message是直接由sPool赋值的。
Handler.obtain()源码
1 2 3 4 5 6 7 8 9
/** * Returns a new {@link android.os.Message Message} from the global message pool. More efficient than * creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this). * If you don't want that facility, just call Message.obtain() instead. */ public final Message obtainMessage() { return Message.obtain(this); }
Handler.obtain()最终还是调用Message.obtain()来获取的。
Message Pool相关源码分析
Message Pool数据结构
1 2 3 4 5 6 7 8 9 10
// sometimes we store linked lists of these things /*package*/ Message next;
/** * Return a Message instance to the global pool. * <p> * You MUST NOT touch the Message after calling this function because it has * effectively been freed. It is an error to recycle a message that is currently * enqueued or that is in the process of being delivered to a Handler. * </p> */ publicvoidrecycle() { if (isInUse()) { if (gCheckRecycle) { thrownew IllegalStateException("This message cannot be recycled because it " + "is still in use."); } return; } recycleUnchecked(); }
/** * Recycles a Message that may be in-use. * Used internally by the MessageQueue and Looper when disposing of queued Messages. */ voidrecycleUnchecked() { // Mark the message as in use while it remains in the recycled object pool. // Clear out all other details. flags = FLAG_IN_USE; what = 0; arg1 = 0; arg2 = 0; obj = null; replyTo = null; sendingUid = -1; when = 0; target = null; callback = null; data = null;
synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this; sPoolSize++; } } }
This memory is used to store the thread data structures and attributes, much of which is allocated as wired memory and therefore cannot be paged to disk.
Stack space
512 KB (secondary threads) 8 MB (OS X main thread) 1 MB (iOS main thread)
The minimum allowed stack size for secondary threads is 16 KB and the stack size must be a multiple of 4 KB. The space for this memory is set aside in your process space at thread creation time, but the actual pages associated with that memory are not created until they are needed.
Creation time
Approximately 90 microseconds
This value reflects the time between the initial call to create the thread and the time at which the thread’s entry point routine began executing. The figures were determined by analyzing the mean and median values generated during thread creation on an Intel-based iMac with a 2 GHz Core Duo processor and 1 GB of RAM running OS X v10.5.
替代线程的一些技术
Item
Approximate cost
Operation objects
Introduced in OS X v10.5, an operation object is a wrapper for a task that would normally be executed on a secondary thread. This wrapper hides the thread management aspects of performing the task, leaving you free to focus on the task itself. You typically use these objects in conjunction with an operation queue object, which actually manages the execution of the operation objects on one or more threads.For more information on how to use operation objects, see Concurrency Programming Guide.
Grand Central Dispatch (GCD)
Introduced in Mac OS x v10.6, Grand Central Dispatch is another alternative to threads that lets you focus on the tasks you need to perform rather than on thread management. With GCD, you define the task you want to perform and add it to a work queue, which handles the scheduling of your task on an appropriate thread. Work queues take into account the number of available cores and the current load to execute your tasks more efficiently than you could do yourself using threads.For information on how to use GCD and work queues, see Concurrency Programming Guide
Idle-time notifications
For tasks that are relatively short and very low priority, idle time notifications let you perform the task at a time when your application is not as busy. Cocoa provides support for idle-time notifications using the NSNotificationQueue object. To request an idle-time notification, post a notification to the default NSNotificationQueue object using the NSPostWhenIdle option. The queue delays the delivery of your notification object until the run loop becomes idle. For more information, see Notification Programming Topics.
Asynchronous functions
The system interfaces include many asynchronous functions that provide automatic concurrency for you. These APIs may use system daemons and processes or create custom threads to perform their task and return the results to you. (The actual implementation is irrelevant because it is separated from your code.) As you design your application, look for functions that offer asynchronous behavior and consider using them instead of using the equivalent synchronous function on a custom thread
Timers
You can use timers on your application’s main thread to perform periodic tasks that are too trivial to require a thread, but which still require servicing at regular intervals. For information on timers, see Timer Sources
Separate processes
Although more heavyweight than threads, creating a separate process might be useful in cases where the task is only tangentially related to your application. You might use a process if a task requires a significant amount of memory or must be executed using root privileges. For example, you might use a 64-bit server process to compute a large data set while your 32-bit application displays the results to the user
Immutable objects are generally thread-safe. Once you create them, you can safely pass these objects to and from threads. On the other hand, mutable objects are generally not thread-safe. To use mutable objects in a threaded application, the application must synchronize appropriately.
Many objects deemed “thread-unsafe” are only unsafe to use from multiple threads. Many of these objects can be used from any thread as long as it is only one thread at a time. Objects that are specifically restricted to the main thread of an application are called out as such
The main thread of the application is responsible for handling events. Although the Application Kit continues to work if other threads are involved in the event path, operations can occur out of sequence
If you want to use a thread to draw to a view, bracket all drawing code between the lockFocusIfCanDraw and unlockFocus methods of NSView
Thread-Safe Classes and Functions
The following classes and functions are generally considered to be thread-safe. You can use the same instance from multiple threads without first acquiring a lock.
The following classes and functions are generally not thread-safe. In most cases, you can use these classes from any thread as long as you use them from only one thread at a time.
Response caching avoids the network completely for repeat requests.
OkHttp supports Android 2.3 and above. For Java, the minimum requirement is 1.7. You’ll also need Okio, which OkHttp uses for fast I/O and resizable buffers.