AFNetWorking的理解.docx
- 文档编号:25538625
- 上传时间:2023-06-09
- 格式:DOCX
- 页数:5
- 大小:17.58KB
AFNetWorking的理解.docx
《AFNetWorking的理解.docx》由会员分享,可在线阅读,更多相关《AFNetWorking的理解.docx(5页珍藏版)》请在冰豆网上搜索。
AFNetWorking的理解
AFNetWorking的理解
先说点题外话,从事ios开发一年,学习了苹果的好多框架,对第三方库也学习了不少,从ios6到ios8,苹果对其库的修改和完善也越来越“大而全”,当然也保留了集成度较低的api,先说说大而全api的好处,用起来很方便,不用你关心内部实现,直接在你的业务逻辑代码中使用他,但是当你根据你自己的业务逻辑进行优化的时候就没办法了,相反集成度较低的api灵活度就好的多,你可以采用自己的独特方法进行管理和使用,当然你付出的代价是自己写好多代码。
有人会问,既然使用者多有自己的业务逻辑,干嘛还要使用大而全的api,其实大而全只是一个相对的概念,库的开发者会根据大多数的使用场景去继承api,那么大部分的应用场景是非常满足的,而且继承的api会提供可配置的参数,总之使用库之前根据场景选择合适的api。
关于AFNetWoring,从事iOS开发的几乎没人不知道,这个库是在NSURLConnection和NSURLSession的基础上进行封装的,逻辑简单清楚,设计思想很好。
1.NSURLConnection中的AFNSRULConnection是苹果IOS2.0之后推出的用于加载URL资源的API,其使用很简单,分为同步和异步异步[objc]viewplaincopyNSURLRequest*request=[[NSURLRequestalloc]initWithURL:
[NSURLURLWithString:
@""]];NSURLConnection*connection=[[NSURLConnectionalloc]initWithRequest:
requestdelegate:
self];[objc]viewplaincopyNSURLRequest*request=[[NSURLRequestalloc]initWithURL:
[NSURLURLWithString:
@""]];[NSURLConnectionsendAsynchronousRequest:
request[objc]viewplaincopy<spanstyle="white-space:
pre"></span>queue:
[NSOperationQueuemainQueue][objc]viewplaincopy<spanstyle="white-space:
pre"></span>completionHandler:
^(NSURLResponse*response,NSData*data,NSError*connectionError){}]同步[objc]viewplaincopyNSURLRequest*request=[[NSURLRequestalloc]initWithURL:
[NSURLURLWithString:
@""]];NSData*data=[NSURLConnectionsendSynchronousRequest:
requestreturningResponse:
nilerror:
nil];解释一下,对于一个URLConnection需要一个URLRequest作为参数,然后才能load其实同步和异步方法底层实现的本质是一样,都是告诉系统请求一个URL资源,系统会有自己私有线程去load,然后load完成后告诉调用者。
而同步方法是,阻塞调用线程,然后一直等待,直到load完成,一般不会在主线程调用同步方法,这样会阻塞用户交互。
异步方法是调用之后就不管了,系统加载完成后会通知调用者,通知调用者的方式有两种,一,代理方式,系统会在connection的调用线程通知代理。
二是queue方式,系统会在调用者指定的queue中通知调用者。
AFnetworing利用的是异步加载数据的方式,而且是代理的方式。
首先我们来做加法讲解。
1,首先一个请求的调用必须有一个线程来执行,那么让哪个线程来做,主线程,还是其他线程,一般情况下没人用主线程,因为app中同时请求很多东西,都放在主线程里面去做那么付出的代价时主线程会各种卡顿,代理的各种交互都得让主线程去处理。
那么就得用子线程。
用子线程做,创建一个NSthread,执行一个NSURLConnection,然后你得指定一个代理,代理是一个object实例,而且这个object必须拥护存储加载数据的功能,整合后就是模型1.NSThread+connection+delegateObject;有问题吗,有,线程并发控制难以控制,那么我们就如何更改这个呢,将NStread换成NSOperation的子类,然后用NSOperation的子类替换delegateObject,那么这样还有一个问题,NSOperation如何控制并发呢,所以我们还缺少NSOpreationQueue。
NSOpreationQueue来管理NSOperation,这样并发就成功了。
整理后为模型2NSOperation+connnetion+NSOperationQueue模型2已经很好了,但是还有一个问题,就是NSOperationQueue在分配一个线程去执行connection,然后load完成后,在后通知这个线程,并调用代理函数执行任务,但是一般情况下,load过程比较慢,系统中会停留一些NSOperation执行线程,并且什么任务都不做,就是等待,所以很浪费。
所以,我们这样考虑,当NSOperationQueue分配一个线程执行NSoperation的时候我们在执行时候,让NSoperation去通知一个共有的线程去执行NSoperation的加载方法,那么NSURLConnection在加载完成后会通知调用线程,这个时候就是这个共有线程,那么其他线程就执行完成然后得以释放解脱,只有一个共有线程在忙碌,这样就不会有浪费。
ok第三种模型出现了NSOperation+connnetion+NSOperationQueue+COMMENThread模型三就是AF采用设计方法。
AF中NSURLConnection的工作流程代码给出源码我们需要请求一个网络资源,我们调用AFHTTPRequestOperationManager中的方法[objc]viewplaincopy-(AFHTTPRequestOperation*)GET:
(NSString*)URLStringparameters:
(id)parameterssuccess:
(void(^)(AFHTTPRequestOperation*operation,idresponseObject))successfailure:
(void(^)(AFHTTPRequestOperation*operation,NSError*error))failure{NSMutableURLRequest*request=[self.requestSerializerrequestWithMethod:
@"GET"URLString:
[[NSURLURLWithString:
URLStringrelativeToURL:
self.baseURL]absoluteString]parameters:
parameterserror:
nil];AFHTTPRequestOperation*operation=[selfHTTPRequestOperationWithRequest:
requestsuccess:
successfailure:
failure];[self.operationQueueaddOperation:
operation];returnoperation;}[objc]viewplaincopy-(AFHTTPRequestOperation*)HTTPRequestOperationWithRequest:
(NSURLRequest*)requestsuccess:
(void(^)(AFHTTPRequestOperation*operation,idresponseObject))successfailure:
(void(^)(AFHTTPRequestOperation*operation,NSError*error))failure{AFHTTPRequestOperation*operation=[[AFHTTPRequestOperationalloc]initWithRequest:
request];operation.responseSerializer=self.responseSerializer;operation.shouldUseCredentialStorage=self.shouldUseCredentialStorage;operation.credential=self.credential;operation.securityPolicy=self.securityPolicy;[operationsetCompletionBlockWithSuccess:
successfailure:
failure];pletionQueue=pletionQueue;pletionGroup=pletionGroup;returnoperation;}[objc]viewplaincopy-(void)setCompletionBlockWithSuccess:
(void(^)(AFHTTPRequestOperation*operation,idresponseObject))successfailure:
(void(^)(AFHTTPRequestOperation*operation,NSError*error))failure{//completionBlockismanuallynilledoutinAFURLConnectionOperationtobreaktheretaincycle.#pragmaclangdiagnosticpush#pragmaclangdiagnosticignored"-Warc-retain-cycles"#pragmaclangdiagnosticignored"-Wgnu"pletionBlock=^{if(pletionGroup){dispatch_group_enter(pletionGroup);}dispatch_async(http_request_operation_processing_queue(),^{if(self.error){if(failure){dispatch_group_async(pletionGroup?
:
http_request_operation_completion_group(),pletionQueue?
:
dispatch_get_main_queue(),^{failure(self,self.error);});}}else{idresponseObject=self.responseObject;if(self.error){if(failure){dispatch_group_async(pletionGroup?
:
http_request_operation_completion_group(),pletionQueue?
:
dispatch_get_main_queue(),^{failure(self,self.error);});}}else{if(success){dispatch_group_async(pletionGroup?
:
http_request_operation_completion_group(),pletionQueue?
:
dispatch_get_main_queue(),^{success(self,responseObject);});}}}if(pletionGroup){dispatch_group_leave(pletionGroup);}});};#pragmaclangdiagnosticpop}这个方法是一个为get的网络请求,AFHTTPRequestOperationManager生成一个AFHTTPRequestOperation,在AFHTTPRequestOperation的构造过程中调用[objc]viewplaincopy-(void)setCompletionBlockWithSuccess:
(void(^)(AFHTTPRequestOperation*operation,idresponseObject))successfailure:
(void(^)(AFHTTPRequestOperation*operation,NSError*error))failure添加完成块。
生成完成后加入到自己的operationQueue中在合适的时机分配线程给AFHTTPRequestOperation,调用AFHTTPRequestOperation的start方法[objc]viewplaincopy-(void)start{[self.locklock];if([selfisCancelled]){[selfperformSelector:
@selector(cancelConnection)onThread:
[[selfclass]networkRequestThread]withObject:
nilwaitUntilDone:
NOmodes:
[self.runLoopModesallObjects]];}elseif([selfisReady]){self.state=AFOperationExecutingState;[selfperformSelector:
@selector(operationDidStart)onThread:
[[selfclass]networkRequestThread]withObject:
nilwaitUntilDone:
NOmodes:
[self.runLoopModesallObjects]];}[self.lockunlock];}start中调用了下面这个函数[objc]viewplaincopy[selfperformSelector:
@selector(operationDidStart)onThread:
[[selfclass]networkRequestThread]withObject:
nilwaitUntilDone:
NOmodes:
[self.runLoopModesallObjects]];这个是中有一个[objc]viewplaincopy[[selfclass]networkRequestThread]这个是干什么的[objc]viewplaincopy+(NSThread*)networkRequestThread{staticNSThread*_networkRequestThread=nil;staticdispatch_once_toncePredicate;dispatch_once(&oncePredicate,^{_networkRequestThread=[[NSThreadalloc]initWithTarget:
selfselector:
@selector(networkRequestThreadEntryPoint:
)object:
nil];[_networkRequestThreadstart];});return_networkRequestThread;}这是AFHTTPRequestOperation中的类方法,也就是说调用多次都会只执行一次,产生了一个共有线程来看AFHTTPRequestOperation让这个共有线程operationDidStart[objc]viewplaincopy-(void)operationDidStart{[self.locklock];if(!
[selfisCancelled]){self.connection=[[NSURLConnectionalloc]initWithRequest:
self.requestdelegate:
selfstartImmediately:
NO];NSRunLoop*runLoop=[NSRunLoopcurrentRunLoop];for(NSString*runLoopModeinself.runLoopModes){[self.connectionscheduleInRunLoop:
runLoopforMode:
runLoopMode];[self.outputStreamscheduleInRunLoop:
runLoopforMode:
runLoopMode];}[self.connectionstart];}[self.lockunlock];dispatch_async(dispatch_get_main_queue(),^{[[NSNotificationCenterdefaultCenter]postNotificationName:
AFNetworkingOperationDidStartNotificationobject:
self];});}这个共有线程创建了一个NSURLConnection,然后异步发送请求,那么NSURLConnection的代理回调也会在这个线程中执行,那么多个网络请求实际上都是让这个共有线程发送,然后接受,一个线程来完成多个发送和接受。
这里有个问题,请求过多的话是否有问题,一个线程忙的过来吗,答案是可以的,因为都是异步,而且无阻塞。
最后完成加载后,执行operation的完成块,执行完成块的线程是系统的一个线程。
思考一下,从并发性的角度来看,AF并没有做什么,根本的并发还是系统底层对NSURLConnection的并发控制,所谓operationQueue的并发是干什么用的,那要是我仅仅用一个线程来收发,并且没个请求都有相应的存储数据的数据结构和完成块就ok了,干嘛要用queue和NSOperation,既然AF用了就有用,因为他们是因为NSOperation可以cancel,可以暂停,等等,而且这些控制都由queue去管理,这样我们自己写的管理代码就少的多,而且我们管理线程肯定不能优于系统,所以,AF这种设计是非常合理的。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- AFNetWorking 理解