美文网首页
AFN为什么添加一条常驻线程

AFN为什么添加一条常驻线程

作者: zziazm | 来源:发表于2018-04-02 15:20 被阅读563次

    以前版本的AF里有这样的代码:

    + (void)networkRequestThreadEntryPoint:(id)__unused object {
        @autoreleasepool {
            [[NSThread currentThread] setName:@"AFNetworking"];
    
            NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
            [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
            [runLoop run];
        }
    }
    
    + (NSThread *)networkRequestThread {
        static NSThread *_networkRequestThread = nil;
        static dispatch_once_t oncePredicate;
        dispatch_once(&oncePredicate, ^{
            _networkRequestThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil];
            [_networkRequestThread start];
        });
        
        return _networkRequestThread;
    }
    

    上面的代码是创建了一个线程并且开启了它的runloop。这个线程就是问题里提到的常驻线程。
    这个线程的作用是什么呢?

    - (void)start {
        [self.lock lock];
        if ([self isReady]) {
            self.state = AFOperationExecutingState;
            
            [self performSelector:@selector(operationDidStart) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
        }
        [self.lock unlock];
    }
    
    - (void)operationDidStart {
        [self.lock lock];
        if (![self isCancelled]) {
            self.connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO];
            
            NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
            for (NSString *runLoopMode in self.runLoopModes) {
                [self.connection scheduleInRunLoop:runLoop forMode:runLoopMode];
                [self.outputStream scheduleInRunLoop:runLoop forMode:runLoopMode];
            }
            
            [self.connection start];
        }
        [self.lock unlock];
        
        dispatch_async(dispatch_get_main_queue(), ^{
            [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidStartNotification object:self];
        });
    }
    

    从上面的代码里可以就看出,AF里面把每一个网络请求的发起和解析都放在了这个线程里执行。正常来说,一个线程执行完任务后就退出了。开启runloop是为了防止线程退出。一方面避免每次请求都要创建新的线程;另一方面,因为connection的请求是异步的,如果不开启runloop,线程执行完代码后不会等待网络请求完的回调就退出了,这会导致网络回调的代理方法不执行。

    总结:AFN 的做法是把网络请求的发起和解析都放在同一个子线程中进行,但由于子线程默认不开启 runloop,它在运行完所有代码后退出线程。而网络请求是异步的,这会导致获取到请求数据时,线程已经退出,代理方法没有机会执行。因此,AFN 的做法是使用一个 runloop 来保证线程不死,能保证代理方法的执行。同时,避免每次请求都创建新的线程。

    相关文章

      网友评论

          本文标题:AFN为什么添加一条常驻线程

          本文链接:https://www.haomeiwen.com/subject/rlithftx.html