源碼閱讀中的收獲

最近在做短視頻相關的模塊,于是在看 GPUImage 的源碼。其實有一定了解的伙伴一定知道 GPUImage 是通過 addTarget 鏈條的形式添加每一個環節。在對于這樣的設計贊嘆之余,想到了實際開發場景下可以用到的場景,借此分享。

我們的項目中應該有很多的聚合頁,每個聚合頁上都有 feed 流,而在很多的項目中 feed 流的場景都是可以進行復用的。而在這樣的場景下我們希望復用的 feed 流中的 cell 可以在多個界面上進行復用。但是如果每一個 cell 上又有幾個點擊事件,如果每一個 Controller 上都有一堆的事件處理代碼,又會代碼冗余量巨大。

開發中遇到的痛點

隨便舉個例子,微博的信息流,微博很多業務都是這樣的界面進行展示,如果每個 cell 的點擊事件代理回 controller 中進行執行,那 controller 有多重可想而知... 而且一旦以后業務調整,某些跳轉頁面更改,波及的頁面之廣,也是無法接受的。

這個時候就會想可不可以在一個地方固定的處理這些事件?

一些解決方案

我記得對于這個問題, 源神 曾經提出過 self-manager 的概念可以解決類似的問題。在源神的解決方案中,feed 按鈕的功能相對單一這樣的方式是一種較好的方案,但是 feed 上的按鈕根據業務場景做不一樣的跳轉,這樣的處理又該如何處理呢? 其實對于源神的方案其實傳入枚舉,對它做對應的處理就可以了。

還是用微博進行舉例,現在我們有A,B,C三條業務線都會對會有 feed 展示這個 cell。

  • A 業務線要求就是要求底部 tabbar 是轉發,評論和點贊的功能
  • B 業務線的要求是轉發的按鈕是跳轉到業務線 A, 評論按鈕的點擊事件跳轉到業務線C,點贊按鈕的功能保留
  • C 業務線的要求是轉發的按鈕跳轉到業務線 B, 評論的按鈕保留原功能,點贊的按鈕跳轉到業務線 B 這樣的操作。

對于這樣的惡心要求(不要覺得我天馬行空,我真的遇到過這類似的業務場景,而且也確實有對應的需要),如果此時還是使用 self-manager,來對狀態進行判斷。可能偽代碼的結構大致如下。

typedef NS_ENUM(NSInteger,BusinessLineType){BusinessLineTypeA = 0,BusinessLineTypeB,BusinessLineTypeC,
}typedef NS_ENUM(NSInteger,CommentBtnHandleType){CommentHandleTypeA = 0,CommentHandleTypeB,CommentHandleTypeC,
}......-(viod)configureCellWithBusiness:(BusinessLineType)businessType{//根據 businseeType 進行判斷 將評論點擊事件的枚舉傳入下一級 然后正確響應點擊事件//根據 businseeType 進行判斷 將轉發按鈕事件根據業務線枚舉講點擊枚舉傳入下一級...}
復制代碼

不知道大家對于這樣的代碼看到后的感受是怎么樣的,但是我可以設想到,在沒有足夠的文檔說明的情況下,如果組里來了一個新的小伙伴或者讓一個對當前業務場景不足夠熟悉的小伙伴進行維護,一定很抓狂,感覺這樣的形式在維護上的成本還是比較高的。所以這樣的方案還是比較適合處理業務上職責比較單一的小塊。

此外對于大廠可能有一條業務線的業務代碼需要使用到多個產品中的情況,這樣的方案一樣也就不再適用了。因為 view 層承接了業務。 而兩個產品的設計并不相同,但是業務的邏輯是相同的,這個時候就不是簡單的替換 view 層就能完成功能添加那么簡單的問題了。

###曾經的方案

基于上邊的復雜業務可讀性差和讓業務和 view 完全解耦的思路,這個時候就需要思考,是不是有更好的處理方案。在一開始我們的項目出現這樣的需求的時候,我想到的解決方案是創建一個事件處理中心的概念。

就是將 cell 中的每一個試圖需要響應事件回調到 cell 層,然后 cell 中有一個 delegate , 創建一個叫 HandleEventCenter 的對象(controller 創建數組維護)來起到回調中心的作用。

這樣對于上邊的需求,我們的處理方案就會變得更加靈活,可以寫一個通用處理一般場景下的基類,然后根據業務線的不同繼承自基類,重寫需要特殊處理的基類的問題。

這是看下這樣處理的優缺點:

  • 解決了 view 層和業務代碼之間代碼耦合的問題,同時事件的處理不需要在每個 controller 上寫多次。同時可以較好的應對點擊事件在不同業務線處理不同邏輯的問題,而且代碼的可讀性問題也得到了解決。

  • 問題就在源神提到的我們要將事件一層層向上回調,寫了很多坨看上去很不爽的回調代碼的問題(無論 delegate 還是 block 都不夠優雅)

更好的處理方案

看到 GPUImage 的源碼之后,我當時想到的方式,就是用這種事件鏈條的形式,將事件傳遞下去就行了。其實在日常開發中,我們都習慣了使用 delegate 或者 block 兩種方式對事件向上進行傳遞,但是忘記了系統很常用的的 target - action 模式。

下邊來看下我們曾經固有模式和現在解決方案的區別。

  • 曾經的方案:我們捕捉到事件執行 -> 傳給上一層(block 或者 代理的模式) -> 再上一層 -> 最后的代理中心 -> 事件響應

  • 現在的解決方案:將事件代理中心 -> 傳遞給 cell 層 -> 傳遞給各個事件層 -> 在事件執行處調用處理中心對應的方法

這樣每層一大堆惡心代碼問題得到了解決,也完全抽離了試圖和業務之間的耦合性。除此之外,如果我們的 cell 上添加了新的響應事件,不需要在層層響應,只需要在處理中心添加新的代理,然后再執行處 target 調用對應方法即可。感覺很大程度上減少了代碼量,同時降低了維護成本。

一些題外話

其實我們在實際的開發中,發現一些特殊的場景下,事件處理中心的方案存在很大的弊端。比如 我們的界面上有一個編輯功能的按鈕,按鈕點擊后,我們會跳轉到一個新的界面對 cell 的數據源進行修改,這個時候再返回,我們需要根據新的數據源刷新當前的 cell 。 事件處理中心的處理方案,就不足以解決這樣復雜的問題,否則就需要和 tableView 產生耦合。當然這樣的問題,我們取巧的進行了解決,本文就不進行介紹了。

提這樣的題外話,不過是想表達每一種方案中可能或多或少的都存在各種各樣的問題,但是針對問題,我們總是可以找到更好的解決方案。總是思考著,我們的程序也終究會變得更好。

當然本文中提到的方案也可能存在各種各樣的問題,希望不吝賜教,希望在探討中找到更平衡的方案。共同進步~~~

最后

之前看源碼,一直關注點都在于技術的細節和如何解決問題上。但是經此發現,在讀源碼的過程中,真的可以思考那些優秀的開源的代碼,為什么這樣設計,在我們日常開發中,這樣的設計是不是可以得到推廣和應用。我相信在這一過程中,不知不覺,大家都會獲得足夠的成長和收獲~~~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/391887.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/391887.shtml
英文地址,請注明出處:http://en.pswp.cn/news/391887.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

馬爾科夫鏈蒙特卡洛_蒙特卡洛·馬可夫鏈

馬爾科夫鏈蒙特卡洛A Monte Carlo Markov Chain (MCMC) is a model describing a sequence of possible events where the probability of each event depends only on the state attained in the previous event. MCMC have a wide array of applications, the most common of…

PAT乙級1012

題目鏈接 https://pintia.cn/problem-sets/994805260223102976/problems/994805311146147840 題解 就比較簡單,判斷每個數字是哪種情況,然后進行相應的計算即可。 下面的代碼中其實數組是不必要的,每取一個數字就可以直接進行相應計算。 // P…

我如何在昌迪加爾大學中心組織Google Hash Code 2019

by Neeraj Negi由Neeraj Negi 我如何在昌迪加爾大學中心組織Google Hash Code 2019 (How I organized Google Hash Code 2019 at Chandigarh University Hub) This is me !!! Neeraj Negi — Google HashCode Organizer這就是我 !!! Neeraj …

leetcode 665. 非遞減數列(貪心算法)

給你一個長度為 n 的整數數組&#xff0c;請你判斷在 最多 改變 1 個元素的情況下&#xff0c;該數組能否變成一個非遞減數列。 我們是這樣定義一個非遞減數列的&#xff1a; 對于數組中所有的 i (0 < i < n-2)&#xff0c;總滿足 nums[i] < nums[i 1]。 示例 1: …

django基于存儲在前端的token用戶認證

一.前提 首先是這個代碼基于前后端分離的API,我們用了django的framework模塊,幫助我們快速的編寫restful規則的接口 前端token原理: 把(token加密后的字符串,keyname)在登入后發到客戶端,以后客戶端再發請求,會攜帶過來服務端截取(token加密后的字符串,keyname),我們再利用解密…

數據分布策略_有效數據項目的三種策略

數據分布策略Many data science projects do not go into production, why is that? There is no doubt in my mind that data science is an efficient tool with impressive performances. However, a successful data project is also about effectiveness: doing the righ…

cell 各自的高度不同的時候

1, cell 根據文字、圖片等內容&#xff0c;確定自己的高度。每一個cell有自己的高度。 2&#xff0c;tableView 初始化 現實的時候&#xff0c;不是從第一個cell開始顯示&#xff0c;&#xff08;從第二個&#xff1f;&#xff09;&#xff0c;非非正常顯示。 a:cell 的高度問題…

leetcode 978. 最長湍流子數組(滑動窗口)

當 A 的子數組 A[i], A[i1], …, A[j] 滿足下列條件時&#xff0c;我們稱其為湍流子數組&#xff1a; 若 i < k < j&#xff0c;當 k 為奇數時&#xff0c; A[k] > A[k1]&#xff0c;且當 k 為偶數時&#xff0c;A[k] < A[k1]&#xff1b; 或 若 i < k < j&…

spring boot源碼下載地址

github下載&#xff1a; https://github.com/spring-projects/spring-boot/tree/1.5.x git地址&#xff1a; https://github.com/spring-projects/spring-boot.git 因為項目中目前使用的就是spring boot 1.5.19版本&#xff0c;因此這里先研究spring boot 1.5版本源碼.轉載于:h…

java基礎學習——5、HashMap實現原理

一、HashMap的數據結構 數組的特點是&#xff1a;尋址容易&#xff0c;插入和刪除困難&#xff1b;而鏈表的特點是&#xff1a;尋址困難&#xff0c;插入和刪除容易。那么我們能不能綜合兩者的特性&#xff0c;做出一種尋址容易&#xff0c;插入刪除也容易的數據結構&#xff1…

看懂nfl定理需要什么知識_NFL球隊為什么不經常通過?

看懂nfl定理需要什么知識Debunking common NFL myths in an analytical study on the true value of passing the ball在關于傳球真實價值的分析研究中揭穿NFL常見神話 Background背景 Analytics are not used enough in the NFL. In a league with an abundance of money, i…

Docker初學者指南-如何創建您的第一個Docker應用程序

您是一名開發人員&#xff0c;并且想要開始使用Docker&#xff1f; 本文是為您準備的。 (You are a developer and you want to start with Docker? This article is made for you.) After a short introduction on what Docker is and why to use it, you will be able to cr…

mybatis if-else(寫法)

mybaits 中沒有else要用chose when otherwise 代替 范例一 <!--批量插入用戶--> <insert id"insertBusinessUserList" parameterType"java.util.List">insert into business_user (id , user_type , user_login )values<foreach collection…

spring—攔截器和異常

SpringMVC的攔截器 SpringMVC攔截器-攔截器的作用 Spring MVC 的攔截器類似于 Servlet 開發中的過濾器 Filter&#xff0c;用于對處理器進行預處理和后處理。 將攔截器按一定的順序聯結成一條鏈&#xff0c;這條鏈稱為攔截器鏈&#xff08;InterceptorChain&#xff09;。在…

29/07/2010 sunrise

** .. We can only appreciate the miracle of a sunrise if we have waited in the darkness .. 人們在黑暗中等待著&#xff0c;那是期盼著如同日出般的神跡出現 .. 附&#xff1a;27/07/2010 sunrise ** --- 31 July 改動轉載于:https://www.cnblogs.com/orderedchaos/archi…

密度聚類dbscan_DBSCAN —基于密度的聚類方法的演練

密度聚類dbscanThe idea of having newer algorithms come into the picture doesn’t make the older ones ‘completely redundant’. British statistician, George E. P. Box had once quoted that, “All models are wrong, but some are useful”, meaning that no model…

node aws 內存溢出_在AWS Elastic Beanstalk上運行生產Node應用程序的現實

node aws 內存溢出by Jared Nutt賈里德努特(Jared Nutt) 在AWS Elastic Beanstalk上運行生產Node應用程序的現實 (The reality of running a production Node app on AWS Elastic Beanstalk) 從在AWS的ELB平臺上運行生產Node應用程序兩年的經驗教訓 (Lessons learned from 2 y…

Day2-數據類型

數據類型與內置方法 數據類型 數字字符串列表字典元組集合字符串 1.用途 用來描述某個物體的特征&#xff1a;姓名&#xff0c;性別&#xff0c;愛好等 2.定義方式 變量名 字符串 如&#xff1a;name huazai 3.常用操作和內置方法 1.按索引取值&#xff1a;&#xff08;只能取…

嵌套路由

父組件不能用精準匹配&#xff0c;否則只組件路由無法展示 轉載于:https://www.cnblogs.com/dianzan/p/11308146.html

leetcode 992. K 個不同整數的子數組(滑動窗口)

給定一個正整數數組 A&#xff0c;如果 A 的某個子數組中不同整數的個數恰好為 K&#xff0c;則稱 A 的這個連續、不一定獨立的子數組為好子數組。 &#xff08;例如&#xff0c;[1,2,3,1,2] 中有 3 個不同的整數&#xff1a;1&#xff0c;2&#xff0c;以及 3。&#xff09; …