AOP編程 - 淘寶京東網路處理

来源:https://www.cnblogs.com/ganchuanpu/archive/2018/01/25/8351008.html
-Advertisement-
Play Games

現象描述 當我們打開京東 app 進入首頁,如果當前是沒有網路的狀態,裡面的按鈕點擊是沒有反應的。只有當我們打開網路的情況下,點擊按鈕才能跳轉頁面,按照我們一般人寫代碼的邏輯應該是這個樣子: 上面這段代碼看似沒有任何問題,完全滿足京東的網路處理需求,就寫一個 if(有網) 跳轉到下一個頁面,沒網就不 ...


現象描述

當我們打開京東 app 進入首頁,如果當前是沒有網路的狀態,裡面的按鈕點擊是沒有反應的。只有當我們打開網路的情況下,點擊按鈕才能跳轉頁面,按照我們一般人寫代碼的邏輯應該是這個樣子:

/**
 * 跳轉到待收貨頁面
 */
public void jumpWaitReceiving() {
    // 判斷當前有沒有網路
    if(CheckNetUtil.isNetworkAvailable(this)) {
        // 當前有網路我才跳轉,進入待收貨頁面
        Intent intent = new Intent(this, WaitReceivingActivity.class);
        startActivity(intent);
    }
}

/**
* 跳轉到我的錢包頁面
*/
public void jumpMineWallet() {
    if(CheckNetUtil.isNetworkAvailable(this)) {
        Intent intent = new Intent(this, MineWalletActivity.class);
        startActivity(intent);
    }
}

上面這段代碼看似沒有任何問題,完全滿足京東的網路處理需求,就寫一個 if(有網) 跳轉到下一個頁面,沒網就不做任何處理。但是真的沒有問題嗎? 按照京東的頁面,這些 if() 代碼估計要寫上幾十次,而且有些在 Activity,有些甚至在 Fragment 中,很難管理。如果有一天需求變動,我們估計要改動多處。我們到底有沒有更好的方式,且接著往下看。

面向切麵

我們現在想做的其實就是,我根本不想寫那麼多的 if() 代碼,而且寫得越多越不好管理,比如有一天沒網路要彈 Toast ,那麼豈不是很多地方要去改動。所以接下來,我們打算採用面向切麵的編程思想,把網路檢測切出來統一管理。第一,保證代碼的簡潔性,第二,需求有變動時我們只需要統一改動那一部分代碼,第三,有很多這裡不一一列出來了。

那麼什麼是 AOP ? 好處又有什麼?

面向切麵(AOP)其實就是把眾多方法中的所有共有代碼全部抽取出來,放置到某個地方集中管理,然後在具體運行時,再由容器動態織入這些共有代碼的話,最起碼可以解決兩個問題:

1.1 Android程式員在編寫具體的業務邏輯處理方法時,只需關心核心的業務邏輯處理,既提高了工作效率,又使代碼變更簡潔優雅。
1.2 在日後的維護中由於業務邏輯代碼與共有代碼分開存放,而且共有代碼是集中存放的,因此使維護工作變得簡單輕鬆。

那到底應該怎麼寫呢? 請看我最終的代碼,代碼如下:

/**
 * 跳轉到待收貨頁面
 */
@CheckNet
public void jumpWaitReceiving() {
    Intent intent = new Intent(this, WaitReceivingActivity.class);
    startActivity(intent);
}

/**
 * 跳轉到我的錢包頁面
 */
@CheckNet
public void jumpMineWallet() {
    Intent intent = new Intent(this, MineWalletActivity.class);
    startActivity(intent);
}
上面這段代碼,也沒看到你省了多少代碼。但其實在我們真正的開發過程中,遠不止檢測網路這麼個功能,比如還需要檢測登錄,需要上傳日誌,統計用戶行為等等。這樣,我們方法越多省的代碼就會越多,而且所有的代碼都統一進行了管理,後面維護起來也方便,況且跟最開始比起來,代碼的確也變得更加簡潔了。那好吧,我們就只看到加了一個 CheckNet ,也沒看到你判斷網路的代碼啊?別急,且接著往下看。最主要的其實還是下麵這段代碼:
 1 /**
 2  * 處理網路檢測切麵
 3  */
 4 @Aspect
 5 public class SectionAspect {
 6 
 7     /**
 8      * 找到處理的切點
 9      * * *(..)  可以處理所有的方法
10      */
11     @Pointcut("execution(@com.darren.architect_day02.CheckNet * *(..))")
12     public void checkNetBehavior() {
13 
14     }
15 
16     /**
17      * 處理切麵
18      */
19     @Around("checkNetBehavior()")
20     public Object checkNet(ProceedingJoinPoint joinPoint) throws Throwable {
21         Log.e("TAG", "checkNet");
22         // 做埋點  日誌上傳  許可權檢測(我寫的,RxPermission , easyPermission) 網路檢測
23         // 網路檢測
24         // 1.獲取 CheckNet 註解  NDK  圖片壓縮  C++ 調用Java 方法
25         MethodSignature signature = (MethodSignature) joinPoint.getSignature();
26         CheckNet checkNet = signature.getMethod().getAnnotation(CheckNet.class);
27         if (checkNet != null) {
28             // 2.判斷有沒有網路  怎麼樣獲取 context?
29             Object object = joinPoint.getThis();// View Activity Fragment ; getThis() 當前切點方法所在的類
30             Context context = getContext(object);
31             if (context != null) {
32                 if (!isNetworkAvailable(context)) {
33                     // 3.沒有網路不要往下執行
34                     Toast.makeText(context,"請檢查您的網路",Toast.LENGTH_LONG).show();
35                     return null;
36                 }
37             }
38         }
39         return joinPoint.proceed();
40     }
41 
42     /**
43      * 通過對象獲取上下文
44      *
45      * @param object
46      * @return
47      */
48     private Context getContext(Object object) {
49         if (object instanceof Activity) {
50             return (Activity) object;
51         } else if (object instanceof Fragment) {
52             Fragment fragment = (Fragment) object;
53             return fragment.getActivity();
54         } else if (object instanceof View) {
55             View view = (View) object;
56             return view.getContext();
57         }
58         return null;
59     }
60 
61     /**
62      * 檢查當前網路是否可用
63      *
64      * @return
65      */
66     private static boolean isNetworkAvailable(Context context) {
67         // 獲取手機所有連接管理對象(包括對wi-fi,net等連接的管理)
68         ConnectivityManager connectivityManager = (ConnectivityManager)
69                 context.getSystemService(Context.CONNECTIVITY_SERVICE);
70         if (connectivityManager != null) {
71             // 獲取NetworkInfo對象
72             NetworkInfo[] networkInfo = connectivityManager.getAllNetworkInfo();
73 
74             if (networkInfo != null && networkInfo.length > 0) {
75                 for (int i = 0; i < networkInfo.length; i++) {
76                     // 判斷當前網路狀態是否為連接狀態
77                     if (networkInfo[i].getState() == NetworkInfo.State.CONNECTED) {
78                         return true;
79                     }
80                 }
81             }
82         }
83         return false;
84     }
85 }

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前段時間因工作需求,特地學習了下sp_send_dbmail的使用,發現網上的示例對我這樣的菜鳥太不友好/(ㄒoㄒ)/~~,好不容易完工來和大家分享一下,不談理論,只管實踐! 如下是實際需求: -- Title: 集團資質一覽表-- Description1:<1、距離到期日期1年內和已過期的發到期 ...
  • [20180124]奇怪的SQL*Net message from dblink.txt--//生產系統出現大量的SQL*Net message from dblink事件,自己分析看看.1.環境:--//這個環境是伺服器在分院,有時候要通過dblink訪問總院的資料庫.xxxx> @ ver1PO ...
  • 中途產生報錯:已連接到空閑常式、ora-03113:通信通道的文件結尾、no login、ora-12514:TNS:監聽程式當前無法識別連接描述符中請求的服務、ora-24324:未初始化服務句柄、ora-03114:未連接到ORACLE、ora-01034:ORACLE not availabl... ...
  • 1.redis-cluster設計 Redis集群搭建的方式有多種,例如使用zookeeper,但從redis 3.0之後版本支持redis-cluster集群,redis-cluster採用無中心結構,每個節點保存數據和整個集群狀態,每個節點都和其他所有節點連接。其redis-cluster架構圖 ...
  • 簡介: RAC 指的就是 RactiveCocoa ,是 Github 的一個開源框架,能夠幫我們提供大量方便的事件處理方案,讓我們更簡單粗暴地去處理事件,現在分為 ReactiveObjC 和 ReactiveSwift ,兩個框架的功能使用相似. RAC 的核心思想:創建信號 - 訂閱信號 -  ...
  • 1、音頻 2、視頻 1、 2、AVPlayer 1、音頻 2、視頻 1、 2、AVPlayer 0)、寫在前面 AVPlayer 主要包含 AVPlayer、AVPlayerItem、AVPlayerLayer,分別對應,控制器C、模型M、視圖V。 1)、AVPlayer(控制器C) 2)、AVPl ...
  • 根據微信的官方文檔,小程式支持打開APP,專門研究了下這個API有什麼,官方文檔地址如下 https://mp.weixin.qq.com/debug/wxadoc/dev/component/button.html launchApp 打開APP,可以通過app-parameter屬性設定向APP ...
  • 說實話,極光推送接觸過好幾遍了,但是每次開發都是實現簡單的展示功能,最近接手的一款app要求只在後臺展示,還要實現點擊通知欄跳轉到相應的詳情界面,於是便以為很簡單的開始了,而且還很嗨的那種,以為自己沒問題了(當時自己用的iOS10以上的iPhone)。但是最後測試階段,出現各種問題,各種調試都不行, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...