国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

深入淺出 OkHttp 源碼解析及應(yīng)用實(shí)踐

這篇具有很好參考價(jià)值的文章主要介紹了深入淺出 OkHttp 源碼解析及應(yīng)用實(shí)踐。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

作者:vivo 互聯(lián)網(wǎng)服務(wù)器團(tuán)隊(duì)- Tie Qinrui

OkHttp 在 Java 和 Android 世界中被廣泛使用,深入學(xué)習(xí)源代碼有助于掌握軟件特性和提高編程水平。

本文首先從源代碼入手簡(jiǎn)要分析了一個(gè)請(qǐng)求發(fā)起過(guò)程中的核心代碼,接著通過(guò)流程圖和架構(gòu)圖概括地介紹了OkHttp的整體結(jié)構(gòu),重點(diǎn)分析了攔截器的責(zé)任鏈模式設(shè)計(jì),最后列舉了OkHttp攔截器在項(xiàng)目中的實(shí)際應(yīng)用。

一、背景介紹

在生產(chǎn)實(shí)踐中,常常會(huì)遇到這樣的場(chǎng)景:需要針對(duì)某一類 Http 請(qǐng)求做統(tǒng)一的處理,例如在 Header 里添加請(qǐng)求參數(shù)或者修改請(qǐng)求響應(yīng)等等。這類問(wèn)題的一種比較優(yōu)雅的解決方案是使用攔截器來(lái)對(duì)請(qǐng)求和響應(yīng)做統(tǒng)一處理。

在 Android 和 Java 世界里 OkHttp 憑借其高效性和易用性被廣泛使用。作為一款優(yōu)秀的開(kāi)源 Http 請(qǐng)求框架,深入了解它的實(shí)現(xiàn)原理,可以學(xué)習(xí)優(yōu)秀軟件的設(shè)計(jì)和編碼經(jīng)驗(yàn),幫助我們更好到地使用它的特性,并且有助于特殊場(chǎng)景下的問(wèn)題排查。本文嘗試從源代碼出發(fā)探究 OkHttp 的基本原理,并列舉了一個(gè)簡(jiǎn)單的例子說(shuō)明攔截器在我們項(xiàng)目中的實(shí)際應(yīng)用。本文源代碼基于 OkHttp 3.10.0。

二、OkHttp 基本原理

2.1 從一個(gè)請(qǐng)求示例出發(fā)

OkHttp 可以用來(lái)發(fā)送同步或異步的請(qǐng)求,異步請(qǐng)求與同步請(qǐng)求的主要區(qū)別在于異步請(qǐng)求會(huì)交由線程池來(lái)調(diào)度請(qǐng)求的執(zhí)行。使用 OkHttp 發(fā)送一個(gè)同步請(qǐng)求的代碼相當(dāng)簡(jiǎn)潔,示例代碼如下:

  • 同步 GET 請(qǐng)求示例

// 1.創(chuàng)建OkHttpClient客戶端
OkHttpClient client = new OkHttpClient();
public String getSync(String url) throws IOException {
      OkHttpClient client = new OkHttpClient();
      // 2.創(chuàng)建一個(gè)Request對(duì)象
      Request request = new Request.Builder()
              .url(url)
              .build();
      // 3.創(chuàng)建一個(gè)Call對(duì)象并調(diào)用execute()方法
      try (Response response = client.newCall(request).execute()) {
          return response.body().string();
      }
  }

其中 execute() 方法是請(qǐng)求發(fā)起的入口,RealCall 對(duì)象的 execute() 方法的源代碼如下:

  • RealCall 的 execute() 方法源代碼

@Override public Response execute() throws IOException {
  synchronized (this) { // 同步鎖定當(dāng)前對(duì)象,將當(dāng)前對(duì)象標(biāo)記為“已執(zhí)行”
    if (executed) throw new IllegalStateException("Already Executed");
    executed = true;
  }
  captureCallStackTrace(); // 捕獲調(diào)用棧
  eventListener.callStart(this); // 事件監(jiān)聽(tīng)器記錄“調(diào)用開(kāi)始”事件
  try {
    client.dispatcher().executed(this); // 調(diào)度器將當(dāng)前對(duì)象放入“運(yùn)行中”隊(duì)列
    Response result = getResponseWithInterceptorChain(); // 通過(guò)攔截器發(fā)起調(diào)用并獲取響應(yīng)
    if (result == null) throw new IOException("Canceled");
    return result;
  } catch (IOException e) {
    eventListener.callFailed(this, e); // 異常時(shí)記錄“調(diào)用失敗事件”
    throw e;
  } finally {
    client.dispatcher().finished(this); // 將當(dāng)前對(duì)象從“運(yùn)行中”隊(duì)列移除
  }
}

execute() 方法首先將當(dāng)前請(qǐng)求標(biāo)記為“已執(zhí)行”,然后會(huì)為重試跟蹤攔截器添加堆棧追蹤信息,接著事件監(jiān)聽(tīng)器記錄“調(diào)用開(kāi)始”事件,調(diào)度器將當(dāng)前對(duì)象放入“運(yùn)行中”隊(duì)列?,之后通過(guò)攔截器發(fā)起調(diào)用并獲取響應(yīng),最后在 finally 塊中將當(dāng)前請(qǐng)求從“運(yùn)行中”隊(duì)列移除,異常發(fā)生時(shí)事件監(jiān)聽(tīng)器記錄“調(diào)用失敗”事件。其中關(guān)鍵的方法是?getResponseWithInterceptorChain() ,其源代碼如下:

Response getResponseWithInterceptorChain() throws IOException {
    // 構(gòu)建一個(gè)全棧的攔截器列表
    List<Interceptor> interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors());
    interceptors.add(retryAndFollowUpInterceptor);
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    interceptors.add(new CacheInterceptor(client.internalCache()));
    interceptors.add(new ConnectInterceptor(client));
    if (!forWebSocket) {
      interceptors.addAll(client.networkInterceptors());
    }
    interceptors.add(new CallServerInterceptor(forWebSocket));
 
    Interceptor.Chain chain = new RealInterceptorChain(interceptors, ……);
 
    return chain.proceed(originalRequest);
  }

該方法中按照特定的順序創(chuàng)建了一個(gè)有序的攔截器列表,之后使用攔截器列表創(chuàng)建攔截器鏈并發(fā)起proceed() 方法調(diào)用。在chain.proceed() 方法中會(huì)使用遞歸的方式將列表中的攔截器串聯(lián)起來(lái)依次對(duì)請(qǐng)求對(duì)象進(jìn)行處理。攔截器鏈的實(shí)現(xiàn)是 OkHttp 的一個(gè)巧妙所在,在后文我們會(huì)用一小節(jié)專門討論。在繼續(xù)往下分析之前,通過(guò)以上的代碼片段我們已經(jīng)大致看到了一個(gè)請(qǐng)求發(fā)起的整體流程。

2.2 OkHttp 核心執(zhí)行流程

一個(gè) OkHttp 請(qǐng)求的核心執(zhí)行過(guò)程如以下流程圖所示:

圖 2-1 OkHttp請(qǐng)求執(zhí)行流程圖

圖中各部分的含義和作用如下:

  • OkHttpClient:是整個(gè) OkHttp 的核心管理類,從面向?qū)ο蟮某橄蟊硎旧蟻?lái)看它代表了客戶端本身,是請(qǐng)求的調(diào)用工廠,用來(lái)發(fā)送請(qǐng)求和讀取響應(yīng)。在大多數(shù)情況下這個(gè)類應(yīng)該是被共享的,因?yàn)槊總€(gè) Client 對(duì)象持有自己的連接池和線程池。重復(fù)創(chuàng)建則會(huì)造成在空閑池上的資源浪費(fèi)。Client對(duì)象可以通過(guò)默認(rèn)的無(wú)參構(gòu)造方法創(chuàng)建也可以通過(guò) Builder 創(chuàng)建自定義的 Client 對(duì)象。Client 持有的線程池和連接池資源在空閑時(shí)可以自動(dòng)釋放無(wú)需客戶端代碼手動(dòng)釋放,在特殊情況下也支持手動(dòng)釋放。

  • Request:一個(gè) Request 對(duì)象代表了一個(gè) Http 請(qǐng)求。它包含了請(qǐng)求地址 url,請(qǐng)求方法類型 method ,請(qǐng)求頭 headers,請(qǐng)求體 body 等屬性,該對(duì)象具有的屬性普遍使用了 final 關(guān)鍵字來(lái)修飾,正如該類的說(shuō)明文檔中所述,當(dāng)這個(gè)類的 body 為空或者 body 本身是不可變對(duì)象時(shí),這個(gè)類是一個(gè)不可變對(duì)象。

  • Response:一個(gè) Response 對(duì)象代表了一個(gè) Http 響應(yīng)。這個(gè)實(shí)例對(duì)象是一個(gè)不可變對(duì)象,只有 responseBody 是一個(gè)可以一次性使用的值,其他屬性都是不可變的。

  • RealCall:一個(gè) RealCall 對(duì)象代表了一個(gè)準(zhǔn)備好執(zhí)行的請(qǐng)求調(diào)用。它只能被執(zhí)行一次。同時(shí)負(fù)責(zé)了調(diào)度和責(zé)任鏈組織的兩大重任。

  • Dispatcher:調(diào)度器。它決定了異步調(diào)用何時(shí)被執(zhí)行,內(nèi)部使用 ExecutorService 調(diào)度執(zhí)行,支持自定義 Executor。

  • EventListener:事件監(jiān)聽(tīng)器。抽象類 EventListener 定義了在一個(gè)請(qǐng)求生命周期中記錄各種事件的方法,通過(guò)監(jiān)聽(tīng)各種事件,可以用來(lái)捕獲應(yīng)用程序 HTTP 請(qǐng)求的執(zhí)行指標(biāo)。從而監(jiān)控 HTTP 調(diào)用的頻率和性能。

  • Interceptor:攔截器。對(duì)應(yīng)了軟件設(shè)計(jì)模式中的攔截器模式,攔截器可用于改變、增強(qiáng)軟件的常規(guī)處理流程,該模式的核心特征是對(duì)軟件系統(tǒng)的改變是透明的和自動(dòng)的。OkHttp 將整個(gè)請(qǐng)求的復(fù)雜邏輯拆分成多個(gè)獨(dú)立的攔截器實(shí)現(xiàn),通過(guò)責(zé)任鏈的設(shè)計(jì)模式將它們串聯(lián)到一起,完成發(fā)送請(qǐng)求獲取響應(yīng)結(jié)果的過(guò)程。

2.3 OkHttp 整體架構(gòu)

通過(guò)進(jìn)一步閱讀 OkHttp 源碼,可以看到 OkHttp 是一個(gè)分層的結(jié)構(gòu)。軟件分層是復(fù)雜系統(tǒng)設(shè)計(jì)的常用手段,通過(guò)分層可以將復(fù)雜問(wèn)題劃分成規(guī)模更小的子問(wèn)題,分而治之。同時(shí)分層的設(shè)計(jì)也有利于功能的封裝和復(fù)用。OkHttp 的架構(gòu)可以分為:應(yīng)用接口層,協(xié)議層,連接層,緩存層,I/O層。不同的攔截器為各個(gè)層次的處理提供調(diào)用入口,攔截器通過(guò)責(zé)任鏈模式串聯(lián)成攔截器鏈,從而完成一個(gè)Http請(qǐng)求的完整處理流程。如下圖所示:

圖 2-2 OkHttp架構(gòu)圖(圖片來(lái)自網(wǎng)絡(luò))

2.4 OkHttp 攔截器的種類和作用

OkHttp 的核心功能是通過(guò)攔截器來(lái)實(shí)現(xiàn)的,各種攔截器的作用分別為:

  • client.interceptors:由開(kāi)發(fā)者設(shè)置的攔截器,會(huì)在所有的攔截器處理之前進(jìn)行最早的攔截處理,可用于添加一些公共參數(shù),如自定義 header、自定義 log 等等。

  • RetryAndFollowUpInterceptor:主要負(fù)責(zé)進(jìn)行重試和重定向的處理。

  • BridgeInterceptor:主要負(fù)責(zé)請(qǐng)求和響應(yīng)的轉(zhuǎn)換。把用戶構(gòu)造的 request 對(duì)象轉(zhuǎn)換成發(fā)送到服務(wù)器 request對(duì)象,并把服務(wù)器返回的響應(yīng)轉(zhuǎn)換為對(duì)用戶友好的響應(yīng)。

  • CacheInterceptor:主要負(fù)責(zé)緩存的相關(guān)處理,將 Http 的請(qǐng)求結(jié)果放到到緩存中,以便在下次進(jìn)行相同的請(qǐng)求時(shí),直接從緩存中讀取結(jié)果,提高響應(yīng)速度。

  • ConnectInterceptor:主要負(fù)責(zé)建立連接,建立 TCP 連接或者 TLS 連接。

  • client.networkInterceptors:由開(kāi)發(fā)者設(shè)置的攔截器,本質(zhì)上和第一個(gè)攔截器類似,但是由于位置不同,所以用處也不同。

  • CallServerInterceptor:主要負(fù)責(zé)網(wǎng)絡(luò)數(shù)據(jù)的請(qǐng)求和響應(yīng),也就是實(shí)際的網(wǎng)絡(luò)I/O操作。將請(qǐng)求頭與請(qǐng)求體發(fā)送給服務(wù)器,以及解析服務(wù)器返回的 response。

除了框架提供的攔截器外,OkHttp 支持用戶自定義攔截器來(lái)對(duì)請(qǐng)求做增強(qiáng)處理,自定義攔截器可以分為兩類,分別是應(yīng)用程序攔截器和網(wǎng)絡(luò)攔截器,他們發(fā)揮作用的層次結(jié)構(gòu)如下圖:

圖 2-3 攔截器(圖片來(lái)自O(shè)kHttp官網(wǎng))

?

不同的攔截器有不同的適用場(chǎng)景,他們各自的優(yōu)缺點(diǎn)如下:

?

應(yīng)用程序攔截器

  • 無(wú)需擔(dān)心重定向和重試等中間響應(yīng)。

  • 總是被調(diào)用一次,即使 HTTP 響應(yīng)是從緩存中提供的。

  • 可以觀察到應(yīng)用程序的原始請(qǐng)求。不關(guān)心 OkHttp 注入的標(biāo)頭。

  • 允許短路而不調(diào)用 Chain.proceed()方法。

  • 允許重試并多次調(diào)用 Chain.proceed()方法。

  • 可以使用 withConnectTimeout、withReadTimeout、withWriteTimeout 調(diào)整呼叫超時(shí)。

?

網(wǎng)絡(luò)攔截器

  • 能夠?qū)χ囟ㄏ蚝椭卦嚨戎虚g響應(yīng)進(jìn)行操作。

  • 緩存響應(yīng)不會(huì)調(diào)用。

  • 可以觀察到通過(guò)網(wǎng)絡(luò)傳輸?shù)脑紨?shù)據(jù)。

  • 可以訪問(wèn)攜帶請(qǐng)求的鏈接。

2.5 責(zé)任鏈模式串聯(lián)攔截器調(diào)用

OkHttp 內(nèi)置了 5 個(gè)核心的攔截器用來(lái)完成請(qǐng)求生命周期中的關(guān)鍵處理,同時(shí)它也支持添加自定義的攔截器來(lái)增強(qiáng)和擴(kuò)展 Http 客戶端,這些攔截器通過(guò)責(zé)任鏈模式串聯(lián)起來(lái),使得的請(qǐng)求可以在不同攔截器之間流轉(zhuǎn)和處理。

2.5.1 責(zé)任鏈模式

責(zé)任鏈模式?是一種行為設(shè)計(jì)模式,?允許將請(qǐng)求沿著處理者鏈發(fā)送。?收到請(qǐng)求后,?每個(gè)處理者均可對(duì)請(qǐng)求進(jìn)行處理,?或?qū)⑵鋫鬟f給鏈上的下一個(gè)處理者。

圖 2-4 責(zé)任鏈(圖片來(lái)自網(wǎng)絡(luò))

適用場(chǎng)景?包括:

  • 當(dāng)程序需要使用不同方式處理不同種類的請(qǐng)求時(shí)

  • 當(dāng)程序必須按順序執(zhí)行多個(gè)處理者時(shí)

  • 當(dāng)所需要的處理者及其順序必須在運(yùn)行時(shí)進(jìn)行改變時(shí)

?

優(yōu)點(diǎn)

  • 可以控制請(qǐng)求處理的順序

  • 可對(duì)發(fā)起操作和執(zhí)行操作的類進(jìn)行解耦。

  • 可以在不更改現(xiàn)有代碼的情況下在程序中新增處理者。

2.5.2 攔截器的串聯(lián)

責(zé)任鏈的入口從第一個(gè) RealInterceptorChain 對(duì)象的 proceed() 方法調(diào)用開(kāi)始。這個(gè)方法的設(shè)計(jì)非常巧妙,在完整的 proceed() 方法里會(huì)做一些更為嚴(yán)謹(jǐn)?shù)男r?yàn),去掉這些校驗(yàn)后該方法的核心代碼如下:

public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec, RealConnection connection) throws IOException {
    if (index >= interceptors.size()) throw new AssertionError();
 
    // ……  
    // Call the next interceptor in the chain.
    RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec, connection, index + 1, request, call, eventListener, connectTimeout, readTimeout, writeTimeout);
    Interceptor interceptor = interceptors.get(index);
    Response response = interceptor.intercept(next);
 
    // ……
    return response;
  }

這段代碼可以看成三個(gè)步驟:

  1. 索引判斷。index 初始值為0,它指示了攔截器對(duì)象在列表中的索引順序,每執(zhí)行一次 proceed 方法該參數(shù)自增1,當(dāng)索引值大于攔截器列表的索引下標(biāo)時(shí)異常退出。

  2. 創(chuàng)建下一個(gè)責(zé)任鏈對(duì)象。

  3. 按照索引順序獲取一個(gè)攔截器,并調(diào)用 intercept() 方法。

?

  • 責(zé)任鏈串聯(lián)

單獨(dú)看這個(gè)方法似乎并不能將所有攔截器都串聯(lián)起來(lái),串聯(lián)的關(guān)鍵在于 intercept() 方法,intercept() 方法是實(shí)現(xiàn) interceptor 接口時(shí)必須要實(shí)現(xiàn)的方法,該方法持有下一個(gè)責(zé)任鏈 對(duì)象 chain,在攔截器的實(shí)現(xiàn)類里只需要在 intercept() 方法里的適當(dāng)?shù)胤皆俅握{(diào)用 chain.proceed() 方法,程序指令便會(huì)重新回到以上代碼片段,于是就可以觸發(fā)對(duì)于下一個(gè)攔截器的查找和調(diào)用了,在這個(gè)過(guò)程中攔截器對(duì)象在列表中的先后順序非常重要,因?yàn)閿r截器的調(diào)用順序就是其在列表中的索引順序。

?

  • 遞歸方法

從另一個(gè)角度來(lái)看,proceed() 方法可以看成是一個(gè)遞歸方法。遞歸方法的基本定義為“函數(shù)的定義中調(diào)用函數(shù)自身”,雖然 proceed() 方法沒(méi)有直接調(diào)用自身,但是除了最后一個(gè)攔截器以外,攔截器鏈中的其他攔截器都會(huì)在適當(dāng)?shù)奈恢谜{(diào)用 chain.proceed() 方法,責(zé)任鏈對(duì)象和攔截器對(duì)象合在一起則組成了一個(gè)自己調(diào)用自己的邏輯循環(huán)。按照筆者個(gè)人理解,這也是為什么源代碼里 Chain 接口被設(shè)計(jì)成 Interceptor 接口的內(nèi)部接口,在理解這段代碼的時(shí)候要把它們兩個(gè)接口當(dāng)成一個(gè)整體來(lái)看,從這樣的角度看的話,這樣的接口設(shè)計(jì)是符合“高內(nèi)聚”的原則的。

?

攔截器 interceptor 和責(zé)任鏈 chain 的關(guān)系如下圖:

圖 2-5 Interceptor 和 Chain 的關(guān)系圖

三、OkHttp 攔截器在項(xiàng)目中的應(yīng)用

在我們的項(xiàng)目中,有一類請(qǐng)求需要在請(qǐng)求頭 Header 中添加認(rèn)證信息,使用攔截器來(lái)實(shí)現(xiàn)可以極大地簡(jiǎn)化代碼,提高代碼可讀性和可維護(hù)性。核心代碼只需要實(shí)現(xiàn)符合業(yè)務(wù)需要的攔截器如下:

  • 添加請(qǐng)求頭的攔截器

public class EncryptInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request originRequest = chain.request();
 
        // 計(jì)算認(rèn)證信息
        String authorization = this.encrypt(originRequest);
         
        // 添加請(qǐng)求頭
        Request request = originRequest.newBuilder()
                .addHeader("Authorization", authorization)
                .build();
        // 向責(zé)任鏈后面?zhèn)鬟f
        return chain.proceed(request);
    }
}

之后在創(chuàng)建 OkHttpClient 客戶端的時(shí)候,使用 addInterceptor() 方法將我們的攔截器注冊(cè)成應(yīng)用程序攔截器,即可實(shí)現(xiàn)自動(dòng)地、無(wú)感地向請(qǐng)求頭中添加實(shí)時(shí)的認(rèn)證信息的功能。

  • 注冊(cè)應(yīng)用程序攔截器

OkHttpClient client = new OkHttpClient.Builder()
    .addInterceptor(new EncryptInterceptor())
    .build();

四、回顧總結(jié)

OkHttp 在 Java 和 Android 世界中被廣泛使用,通過(guò)使用 OkHttp 攔截器可以解決一類問(wèn)題——針對(duì)一類請(qǐng)求統(tǒng)一修改請(qǐng)求或響應(yīng)內(nèi)容。深入了解 OkHttp 的設(shè)計(jì)和實(shí)現(xiàn)不僅可以幫助我們學(xué)習(xí)優(yōu)秀開(kāi)源軟件的設(shè)計(jì)和編碼經(jīng)驗(yàn),也有利于更好地使用軟件特性以及對(duì)特殊場(chǎng)景下問(wèn)題的排查。本文嘗試從一個(gè)同步 GET 請(qǐng)求的例子開(kāi)始,首先通過(guò)源代碼片段簡(jiǎn)要分析了一個(gè)請(qǐng)求發(fā)起過(guò)程中涉及的核心代碼,接著用流程圖的形式總結(jié)了請(qǐng)求執(zhí)行過(guò)程,然后用架構(gòu)圖展示了OkHttp的分層設(shè)計(jì),介紹了各種攔截器的用途、工作層次及優(yōu)缺點(diǎn),之后著重分析了攔截器的責(zé)任鏈模式設(shè)計(jì)——本質(zhì)是一個(gè)遞歸調(diào)用,最后用一個(gè)簡(jiǎn)單的例子介紹了 OkHttp 攔截器在實(shí)際生產(chǎn)場(chǎng)景中的應(yīng)用。

?

參考:

  1. OkHttp官方文檔

  2. OkHttp源碼解析系列文章文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-450161.html

到了這里,關(guān)于深入淺出 OkHttp 源碼解析及應(yīng)用實(shí)踐的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 深入淺出:FFmpeg 音頻解碼與處理AVFrame全解析

    深入淺出:FFmpeg 音頻解碼與處理AVFrame全解析

    FFmpeg 是一個(gè)開(kāi)源的音視頻處理軟件,它包含了一系列的庫(kù)和程序,用于處理音頻、視頻和其他多媒體數(shù)據(jù)。FFmpeg 的名字來(lái)源于 “Fast Forward MPEG”,其中 MPEG 是一種常見(jiàn)的音視頻編碼標(biāo)準(zhǔn)。 FFmpeg 項(xiàng)目于 2000 年由 Fabrice Bellard 啟動(dòng),他是 QEMU(一種開(kāi)源的計(jì)算機(jī)模擬器和虛擬機(jī)

    2024年02月04日
    瀏覽(41)
  • 【深入淺出C#】章節(jié)10: 最佳實(shí)踐和性能優(yōu)化:內(nèi)存管理和資源釋放

    一、 內(nèi)存管理基礎(chǔ) 1.1 垃圾回收機(jī)制 垃圾回收概述 垃圾回收(Garbage Collection)是一種計(jì)算機(jī)科學(xué)和編程領(lǐng)域的重要概念,它主要用于自動(dòng)管理計(jì)算機(jī)程序中的內(nèi)存分配和釋放。垃圾回收的目標(biāo)是識(shí)別和回收不再被程序使用的內(nèi)存,以便釋放資源并防止內(nèi)存泄漏,從而提高程

    2024年02月09日
    瀏覽(27)
  • 深入淺出解析LoRA完整核心基礎(chǔ)知識(shí) | 【算法兵器譜】

    深入淺出解析LoRA完整核心基礎(chǔ)知識(shí) | 【算法兵器譜】

    Rocky Ding 公眾號(hào):WeThinkIn 【算法兵器譜】欄目專注分享AI行業(yè)中的前沿/經(jīng)典/必備的模型論文,并對(duì)具備劃時(shí)代意義的模型論文進(jìn)行全方位系統(tǒng)的解析,比如Rocky之前出品的爆款文章Make YOLO Great Again系列。也歡迎大家提出寶貴的優(yōu)化建議,一起交流學(xué)習(xí)?? 大家好,我是Rocky。

    2024年02月11日
    瀏覽(27)
  • 深入淺出阿里數(shù)據(jù)同步神器:Canal原理+配置+實(shí)戰(zhàn)全網(wǎng)最全解析!

    深入淺出阿里數(shù)據(jù)同步神器:Canal原理+配置+實(shí)戰(zhàn)全網(wǎng)最全解析!

    canal 翻譯為管道,主要用途是基于 MySQL 數(shù)據(jù)庫(kù)的增量日志 Binlog 解析,提供增量數(shù)據(jù)訂閱和消費(fèi)。 早期阿里巴巴因?yàn)楹贾莺兔绹?guó)雙機(jī)房部署,存在跨機(jī)房同步的業(yè)務(wù)需求,實(shí)現(xiàn)方式主要是基于業(yè)務(wù) trigger 獲取增量變更。從 2010 年開(kāi)始,業(yè)務(wù)逐步嘗試數(shù)據(jù)庫(kù)日志解析獲取增量變

    2024年02月10日
    瀏覽(23)
  • 深入淺出:?jiǎn)捂湵淼膶?shí)現(xiàn)和應(yīng)用

    深入淺出:?jiǎn)捂湵淼膶?shí)現(xiàn)和應(yīng)用

    ? ??博客主頁(yè):青竹霧色間. ??博客制作不易歡迎各位??點(diǎn)贊+?收藏+?關(guān)注 ?? 人生如寄,多憂何為? ? 目錄 前言 單鏈表的基本概念 節(jié)點(diǎn) 頭節(jié)點(diǎn) 尾節(jié)點(diǎn) 單鏈表的基本操作 創(chuàng)建單鏈表 頭插法: 尾插法: 插入(增)操作 ?刪除(刪)操作: 查找(查)操作: 修改(改

    2024年02月08日
    瀏覽(15)
  • 深入淺出解析Stable Diffusion完整核心基礎(chǔ)知識(shí) | 【算法兵器譜】

    深入淺出解析Stable Diffusion完整核心基礎(chǔ)知識(shí) | 【算法兵器譜】

    Rocky Ding 公眾號(hào):WeThinkIn 最新更新: Rocky也一直在更新Stable Diffusion系列的文章內(nèi)容,包括最新發(fā)布的Stable Diffusion XL。Rocky都進(jìn)行了全方位的深入淺出的解析, 碼字真心不易,希望大家能給Rocky正在撰寫更新的下面兩篇文章多多點(diǎn)贊,萬(wàn)分感謝: 深入淺出完整解析Stable Diffus

    2024年02月10日
    瀏覽(25)
  • 【知識(shí)圖譜】深入淺出講解知識(shí)圖譜(技術(shù)、構(gòu)建、應(yīng)用)

    【知識(shí)圖譜】深入淺出講解知識(shí)圖譜(技術(shù)、構(gòu)建、應(yīng)用)

    本文收錄于《深入淺出講解自然語(yǔ)言處理》專欄,此專欄聚焦于自然語(yǔ)言處理領(lǐng)域的各大經(jīng)典算法,將持續(xù)更新,歡迎大家訂閱! 個(gè)人主頁(yè):有夢(mèng)想的程序星空 個(gè)人介紹:小編是人工智能領(lǐng)域碩士,全棧工程師,深耕Flask后端開(kāi)發(fā)、數(shù)據(jù)挖掘、NLP、Android開(kāi)發(fā)、自動(dòng)化等領(lǐng)域

    2023年04月08日
    瀏覽(64)
  • 【深入淺出】條件概率的鏈?zhǔn)椒▌t:定義、公式與應(yīng)用

    【深入淺出】條件概率的鏈?zhǔn)椒▌t:定義、公式與應(yīng)用

    在概率論的研究中,條件概率是一種非常重要的概念。當(dāng)多個(gè)隨機(jī)事件發(fā)生時(shí),我們有時(shí)需要考慮它們同時(shí)發(fā)生的概率。條件概率的鏈?zhǔn)椒▌t就是一種用于計(jì)算多個(gè)隨機(jī)事件同時(shí)發(fā)生的概率的方法。本文將會(huì)介紹條件概率的鏈?zhǔn)椒▌t的定義、公式以及應(yīng)用。 條件概率是指在已

    2024年02月08日
    瀏覽(24)
  • 深入淺出落地應(yīng)用分析:AI數(shù)字人「微軟小冰」

    深入淺出落地應(yīng)用分析:AI數(shù)字人「微軟小冰」

    hi,各位,今天要聊的是AI小冰,機(jī)緣巧合,投遞了這家公司的產(chǎn)品,正好最近在看數(shù)字人相關(guān)的,就詳細(xì)剖析下這款產(chǎn)品! 小冰,全稱為北京紅棉小冰科技有限公司,前身為微軟(亞洲)互聯(lián)網(wǎng)工程院人工智能小冰團(tuán)隊(duì),是微軟全球最大的人工智能獨(dú)立產(chǎn)品研發(fā)團(tuán)隊(duì)。作為

    2024年03月20日
    瀏覽(33)
  • 深入淺出Rust內(nèi)存安全:構(gòu)建更安全、高效的系統(tǒng)應(yīng)用

    深入淺出Rust內(nèi)存安全:構(gòu)建更安全、高效的系統(tǒng)應(yīng)用

    在過(guò)去幾年中,Rust編程語(yǔ)言以其獨(dú)特的安全保障特性和高效的性能,成為了眾多開(kāi)發(fā)者和大型科技公司的新寵。尤其是其內(nèi)存安全特性,成為了廣泛討論和贊揚(yáng)的焦點(diǎn)。本文旨在深入探討內(nèi)存安全的概念、Rust在內(nèi)存安全方面的獨(dú)到之處,以及這些特性對(duì)系統(tǒng)開(kāi)發(fā)的深遠(yuǎn)影響

    2024年02月19日
    瀏覽(32)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包