日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

facebook的network-connection-class(测量移动端网络质量)源码详解

發布時間:2023/12/16 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 facebook的network-connection-class(测量移动端网络质量)源码详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近逛github,突然發現facebook居然寫了個檢測網絡質量的框架源碼地址,好奇心驅使那就研究一下吧。分析源碼之前,先看一看官方給我們提供的例子效果:



這個是faceBook官方為這個小框架提供的demo,點擊Test按鈕即可測出當前手機網絡速度的質量,但是這里出現了一串英文EXCELLENT,什么鬼這表示的速度是什么,查詢源碼找到包含參數的這個枚舉類

public enum ConnectionQuality {/*** Bandwidth under 150 kbps.*/POOR,/*** Bandwidth between 150 and 550 kbps.*/MODERATE,/*** Bandwidth between 550 and 2000 kbps.*/GOOD,/*** EXCELLENT - Bandwidth over 2000 kbps.*/EXCELLENT,/*** Placeholder for unknown bandwidth. This is the initial value and will stay at this value* if a bandwidth cannot be accurately found.*/UNKNOWN }
英文已經說明的很清楚了,測試的當前網絡速度2000 kbps以上,說明手機當前網絡質量不錯吆!好,看完例子,接下來進入重點

mConnectionClassManager = ConnectionClassManager.getInstance();mDeviceBandwidthSampler = DeviceBandwidthSampler.getInstance();.....mListener = new ConnectionChangedListener();

@Overrideprotected void onPause() {super.onPause();mConnectionClassManager.remove(mListener);}@Overrideprotected void onResume() {super.onResume();mConnectionClassManager.register(mListener);}
例子當中與框架交互的首先映入眼簾的就是這幾句代碼,可以看到,小框架中聲明了兩個單例ConnectionClassManager類和DeviceBandwidthSampler類,然后通過ConnectionClassManager注冊了一個監聽回調方法,用于顯示網絡變化,既然是一直在監聽網絡速度變化的,那么八成會有死循環一直運行監測網速。ok,先看看DeviceBandwidthSampler類,驗證一下推論。

private DeviceBandwidthSampler(ConnectionClassManager connectionClassManager) {mConnectionClassManager = connectionClassManager;mSamplingCounter = new AtomicInteger();mThread = new HandlerThread("ParseThread");mThread.start();mHandler = new SamplingHandler(mThread.getLooper());} 這個類的構造方法聲明了一個HandlerThread,看到 HandlerThread,已經能看出來,它是想在在線程當中執行消息隊列,start()方法創建一個新的消息隊列管理,類Loop,然后進行輪詢查看是否有消息,有消息就處理,接下來創建一個綁定這個 HandlerThread的Loop的Handler,用來發消息。按照猜測接下來就是利用Handler來循環傳送消息了,在點擊按鈕下載圖片的時候調用了?mDeviceBandwidthSampler.startSampling()方法發送了消息。

/*** 開始檢測網絡速度*/public void startSampling() {if (mSamplingCounter.getAndIncrement() == 0) {//看這里mHandler.startSamplingThread();mLastTimeReading = SystemClock.elapsedRealtime();}} public void startSamplingThread() {sendEmptyMessage(SamplingHandler.MSG_START);} 看這個方法鏈的調用,最終通過發消息的方式實現循環


public void handleMessage(Message msg) {switch (msg.what) {case MSG_START:addSample();sendEmptyMessageDelayed(MSG_START, SAMPLE_TIME);
消息處理中每隔一段時間重新發送相通消息,那么計算處理網絡速度的也只有 addSample方法了


protected void addSample() {//得到手機自啟動以來的總共消耗的流量long newBytes = TrafficStats.getTotalRxBytes();long byteDiff = newBytes - sPreviousBytes;//有變化的時候才去計算if (sPreviousBytes >= 0) {synchronized (this) {//得到當前的時間long curTimeReading = SystemClock.elapsedRealtime();//傳入流量變化的差值和時間差值mConnectionClassManager.addBandwidth(byteDiff, curTimeReading - mLastTimeReading);mLastTimeReading = curTimeReading;}}sPreviousBytes = newBytes;}
這個方法首先獲得了手機自啟動以來的流量消耗的總量,然后用當前量減去上一次的量,也就是說網絡速度是通過單位時間內流量的差值進行計算的,接下來進入?mConnectionClassManager.addBandwidth進行計算

public synchronized void addBandwidth(long bytes, long timeInMs) {// Ignore garbage values.// 變化量小于10計算終止重新記錄值if (timeInMs == 0|| (bytes) * 1.0 / (timeInMs) * BYTES_TO_BITS < BANDWIDTH_LOWER_BOUND) {return;}double bandwidth = (bytes) * 1.0 / (timeInMs) * BYTES_TO_BITS;mDownloadBandwidth.addMeasurement(bandwidth);// 如果它為true連續mSampleCounter+1if (mInitiateStateChange) {mSampleCounter += 1;// 判斷當前的值和期望的值是否處在同一個范圍內,不處在同一個范圍內,連續5次計算的值和波動值在同一個范圍內的話,減少網絡波動造成的誤差if (getCurrentBandwidthQuality() != mNextBandwidthConnectionQuality.get()) {// 計數重新開始,mInitiateStateChangemInitiateStateChange = false;mSampleCounter = 1;}/*** 網絡穩定到5次以上才通知計算結果,波動比較大的時候不通知,優化更準確*/if (mSampleCounter >= DEFAULT_SAMPLES_TO_QUALITY_CHANGE&& significantlyOutsideCurrentBand()) {mInitiateStateChange = false;mSampleCounter = 1;// 確定改變的時候設置通知mCurrentBandwidthConnectionQuality.set(mNextBandwidthConnectionQuality.get());notifyListeners();}return;}// 如果上一個速率和現在的計算速率不一樣,那么mInitiateStateChange=true,mNextBandwidthConnectionQuality儲存當前的速錄if (mCurrentBandwidthConnectionQuality.get() != getCurrentBandwidthQuality()) {mInitiateStateChange = true;mNextBandwidthConnectionQuality = new AtomicReference<ConnectionQuality>(getCurrentBandwidthQuality());}}
計算的核心都在這個方法里面,首先判斷如果前后消耗流量的變化小于10kbs那么,重新記錄值計算終止,滿足條件通過mDownloadBandwidth.addMeasurement方法計算出變化的平均值,也就是通過指數移動平均值來重新估算這個差值,由于移動網絡的不穩定性,通過計算平均值計算會更準確,假設當前網絡已經有了上一次的速度,但是由于某種原因,速度發生變化,比如信號不好,那么此時為了排除誤差,采取連續計算五次方式,也就是說如果當前網絡速度變化值滿足五次在同一個范圍內并且和上一次計算的速度不在同一范圍內的話,那么通知客戶端速度改變,當前速度值刷新,也就是網絡速度值必須保持5次計算都在同一個范圍內,才認為當前網絡質量的速度為準確的,也就是說假設當前速度為100kbs,信號突然不好掉到30kbs,但是有可能信號又突然恢復了,那么當前速度還是100kbs,沒必要通知客戶端網絡速度發生了改變。這種方式可以是測量值更接近真實情況的值,當然不肯能100%準確。


最后看一下指數移動平均值是怎么計算的

public void addMeasurement(double measurement) {// 0.95double keepConstant = 1 - mDecayConstant;// 累加次數大于20次if (mCount > mCutover) {// 自然對數Math.log(mValue),Math.exp() 函數返回 exmValue = Math.exp(keepConstant * Math.log(mValue) + mDecayConstant* Math.log(measurement));}// 0<mCount<20走這里else if (mCount > 0) {// 如果mCount是4的話double retained = keepConstant * mCount / (mCount + 1.0);double newcomer = 1.0 - retained;mValue = Math.exp(retained * Math.log(mValue) + newcomer* Math.log(measurement));}// 第一次mCount是等于0的else {mValue = measurement;}mCount++;} 指數平均值通過前后變化的兩個數進行權重平均值計算,至于這樣計算為什么準確,筆者暫時有點懵逼,但是這個算法是統計學當中的,不管怎么說閱讀此代碼讓筆者了解到,想成為高手中的戰斗機算法必須牛,那么接下來的目標就是拾起曾經遺忘的數學



總結

以上是生活随笔為你收集整理的facebook的network-connection-class(测量移动端网络质量)源码详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。