一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

您好,歡迎來電子發(fā)燒友網(wǎng)! ,新用戶?[免費(fèi)注冊(cè)]

您的位置:電子發(fā)燒友網(wǎng)>源碼下載>通訊/手機(jī)編程>

封裝下載管理器實(shí)例教學(xué)

大?。?/span>0.3 MB 人氣: 2017-09-26 需要積分:1

  第一節(jié):功能說明

  首先,本篇文章教大家寫一個(gè)最簡(jiǎn)單的下載管理器,不包含上傳管理器。不過,上傳管理器與下載管理器是一樣的,后面會(huì)拋磚引玉,大家可以各自去嘗試!

  本篇文章所講解的下載管理器具備以下功能:

  開始下載某個(gè)視頻

  掛起某個(gè)視頻下載(暫停下載)

  恢復(fù)某個(gè)視頻下載(繼續(xù)下載)

  可設(shè)置下載最大并發(fā)量

  添加到下載隊(duì)列

  以下便是最基本的功能了,那么我們就根據(jù)這幾個(gè)基本功能來實(shí)現(xiàn)。至于要做到后臺(tái)自動(dòng)下載及退出App,下次進(jìn)入再自動(dòng)恢復(fù)到上一次退出的狀態(tài)的,這些不在本demo范圍之內(nèi)!

  為了demo的簡(jiǎn)單,一切從簡(jiǎn)!

  第二節(jié):設(shè)計(jì)理念

  設(shè)計(jì)理念通常都希望簡(jiǎn)單使用且易擴(kuò)展易維護(hù)

  與具體的下載類型無關(guān),比如不管是視頻下載還是音頻下載又或是普通文件下載,都沒有關(guān)系,都可通用

  單個(gè)下載應(yīng)保持功能的單一性,專心做一件事

  第三節(jié):如何設(shè)計(jì)整個(gè)下載管理器

  考慮到需要記錄進(jìn)度及狀態(tài),所以一旦開啟下載,整個(gè)app過程中都會(huì)存在,可考慮使用單例,也可以考慮非單例,但是非單例模式也得保證只創(chuàng)建一遍并交給appDelegate持有,其實(shí)與單例設(shè)計(jì)相當(dāng)?shù)?。為了?jiǎn)化,這里采用的是單例設(shè)計(jì)。所以,下載管理器以單例形式存在。

  考慮到需要處理并發(fā)下載問題,因此使用NSOperationQueue

  考慮到下載類的功能單一性,采用子類化NSOperation

  考慮到使用下載功能與文件類型無關(guān),可定義協(xié)議,使model必須遵守,比如豆瓣開源的DOUAudioStreamer就是采用這種方式來實(shí)現(xiàn)

  但是,為了demo的簡(jiǎn)單,這里沒有定義協(xié)議,直接使用model了。大家可以在真正設(shè)計(jì)時(shí),采用協(xié)議的式,以支持任意model。筆者在項(xiàng)目中真正去寫的時(shí)候,也會(huì)采用協(xié)議的方式,支持下載、上傳做任意類型的文件,包括視頻、音頻等。

  本demo中,主要設(shè)計(jì)以下幾個(gè)類:

  HYBVideoOperation:子類化的NSOperation,用于專門做下載

  HYBVideoModel:視頻下載數(shù)據(jù)模型,包括視頻下載地址、存儲(chǔ)地址、進(jìn)度、狀態(tài)等,并持有HYBVideoOperation,以方便管理

  HYBVideoManager:下載管理器,管理所有的HYBVideoModel

  然后,我們還需要與UI交互,所以在cell中需要model。HYBVideoCell類為cell,強(qiáng)引用model!

  那么,這整個(gè)交互是這樣的:

  HYBVideoManager —–》管理所有的HYBVideoModel

  每個(gè)HYBVideoModel—–》持有一個(gè)HYBVideoOperation

  HYBVideoOperation—-》弱持有一個(gè)HYBVideoModel

  HYBVideoCell —–》持有一個(gè)HYBVideoModel,當(dāng)進(jìn)度或狀態(tài)變化時(shí),更新UI

  所設(shè)計(jì)的回調(diào)全放在HYBVideoModel中,當(dāng)HYBVideoModel的進(jìn)度屬性值和狀態(tài)值發(fā)生變化時(shí)反饋到UI變化上!

  第四節(jié):子類化NSOperation

  關(guān)于子類化NSOperation需要做哪些事件,最好還是先閱讀筆者之前所寫的一篇文章NSOperation/Queue,不過下面我也會(huì)列出一些要點(diǎn):

  重寫start方法時(shí),要做好isCannelled的判斷

  重寫isExecuting、isFinished、isConcurrent

  重寫cancel,并處理好isCancelled KVO處理

  我們?cè)O(shè)計(jì)Operation時(shí),采用NSURLSession實(shí)現(xiàn)下載,通過控制NSURLSessionDownloadTask,可實(shí)現(xiàn)下載、暫停下載和斷點(diǎn)下載功能。

  我們整個(gè)頭文件的設(shè)計(jì)為:

  @class HYBVideoModel;

  @interface NSURLSessionTask (VideoModel)

  // 為了更方便去獲取,而不需要遍歷,采用擴(kuò)展的方式,可直接提取,提高效率

  @property (nonatomic, weak) HYBVideoModel *hyb_videoModel;

  @end

  @interface HYBVideoOperation : NSOperation

  - (instancetype)initWithModel:(HYBVideoModel *)model session:(NSURLSession *)session;

  @property (nonatomic, weak) HYBVideoModel *model;

  // 可以不公開此屬性

  @property (nonatomic, strong, readonly) NSURLSessionDownloadTask *downloadTask;

  - (void)suspend;

  - (void)resume;

  - (void)downloadFinished;

  @end

  這里還擴(kuò)展了NSURLSessionTask,將模型與之關(guān)聯(lián),注意采用弱引用哦!我不知道這樣設(shè)計(jì)是否合理,但是我個(gè)人認(rèn)為這么設(shè)計(jì)的好處是:接口簡(jiǎn)單,與外部沒有直接的聯(lián)系,session來源于下載管理類,這樣可統(tǒng)一管理。

  當(dāng)下載完成之后,一定要回調(diào)downloadFinished,目的是讓任務(wù)退隊(duì)。要讓任務(wù)退隊(duì),只有保證isFinished為YES才能退隊(duì)!

 ?。踫elf willChangeValueForKey:@“isFinished”];

 ?。踫elf willChangeValueForKey:@“isExecuting”];

  _executing = NO;

  _finished = YES;

  [self didChangeValueForKey:@“isExecuting”];

 ?。踫elf didChangeValueForKey:@“isFinished”];

  因?yàn)槿蝿?wù)完成還可以重新下載,通常情況下不會(huì)自動(dòng)退隊(duì)。

  第五節(jié):反饋到UI展示進(jìn)度及狀態(tài)提示

  我們通過模型來反饋到UI上,在進(jìn)度和狀態(tài)變化時(shí),可以回調(diào)來更新UI。

  首先,下載過程有很多種狀態(tài),我們定義成枚舉:

  typedef NS_ENUM(NSInteger, HYBVideoStatus) {

  kHYBVideoStatusNone = 0, // 初始狀態(tài)

  kHYBVideoStatusRunning = 1, // 下載中

  kHYBVideoStatusSuspended = 2, // 下載暫停

  kHYBVideoStatusCompleted = 3, // 下載完成

  kHYBVideoStatusFailed = 4, // 下載失敗

  kHYBVideoStatusWaiting = 5 // 等待下載

  };

  設(shè)計(jì)屬性:

  typedef void(^HYBVideoStatusChanged)(HYBVideoModel *model);

  typedef void(^HYBVideoProgressChanged)(HYBVideoModel *model);

  @interface HYBVideoModel : NSObject

  @property (nonatomic, copy) NSString *videoId;

  @property (nonatomic, copy) NSString *videoUrl;

  @property (nonatomic, copy) NSString *imageUrl;

  @property (nonatomic, copy) NSString *title;

  // 用于斷點(diǎn)下載記錄,其實(shí)應(yīng)該要存儲(chǔ)到文件中,然后記錄路徑,但是為了簡(jiǎn)單,demo就不這么做了

  @property (nonatomic, strong) NSData *resumeData;

  // 下載后存儲(chǔ)到此處

  @property (nonatomic, copy) NSString *localPath;

  @property (nonatomic, copy) NSString *progressText;

  // 非常關(guān)鍵的屬性,進(jìn)度變化會(huì)自動(dòng)回調(diào)onProgressChanged

  @property (nonatomic, assign) CGFloat progress;

  // 狀態(tài)變化會(huì)自動(dòng)回調(diào)onStatusChanged

  @property (nonatomic, assign) HYBVideoStatus status;

  // 這里為什么要引用operation且是強(qiáng)引用?因?yàn)楣芾砥髦苯庸芾淼氖莔odel,

  // 而真正做下載任務(wù)的是operation。

  // 為什么沒有將這兩個(gè)分別作為屬性呢?為了整體更簡(jiǎn)單!

  @property (nonatomic, strong) HYBVideoOperation *operation;

  @property (nonatomic, copy) HYBVideoStatusChanged onStatusChanged;

  @property (nonatomic, copy) HYBVideoProgressChanged onProgressChanged;

  @property (nonatomic, readonly, copy) NSString *statusText;

  @end

  當(dāng)然,不同的人來設(shè)計(jì),可能會(huì)有不同的方式。我分析過好幾種設(shè)計(jì)方式,但是列出來的好處,不如這一種。

  當(dāng)進(jìn)度或者狀態(tài)變化時(shí),自動(dòng)地回調(diào):

  - (void)setProgress:(CGFloat)progress {

  if (_progress != progress) {

  _progress = progress;

  if (self.onProgressChanged) {

  self.onProgressChanged(self);

  } else {

  NSLog(@“progress changed block is empty”);

  }

  }

  }

  - (void)setStatus:(HYBVideoStatus)status {

  if (_status != status) {

  _status = status;

  if (self.onStatusChanged) {

  self.onStatusChanged(self);

  }

  }

  }

  這樣回調(diào)與下載管理類及下載類都沒有直接的關(guān)系了,而model的回調(diào)直接反饋到UI層了!

非常好我支持^.^

(0) 0%

不好我反對(duì)

(0) 0%

      發(fā)表評(píng)論

      用戶評(píng)論
      評(píng)價(jià):好評(píng)中評(píng)差評(píng)

      發(fā)表評(píng)論,獲取積分! 請(qǐng)遵守相關(guān)規(guī)定!

      ?