For Android Developer, many open source libraries are essential knowledge points for development, from the use of ways to implementation principles to source code parsing, which require us to have a certain degree of understanding and application ability. So I’m going to write a series of articles about source code analysis and practice of open source libraries, the initial target is EventBus, ARouter, LeakCanary, Retrofit, Glide, OkHttp, Coil and other seven well-known open source libraries, hope to help you 😇😇
Official account: byte array
Article Series Navigation:
- Tripartite library source notes (1) -EventBus source detailed explanation
- Tripartite library source notes (2) -EventBus itself to implement one
- Three party library source notes (3) -ARouter source detailed explanation
- Third party library source notes (4) -ARouter own implementation
- Three database source notes (5) -LeakCanary source detailed explanation
- Tripartite Library source note (6) -LeakCanary Read on
- Tripartite library source notes (7) -Retrofit source detailed explanation
- Tripartite library source notes (8) -Retrofit in combination with LiveData
- Three party library source notes (9) -Glide source detailed explanation
- Tripartite library source notes (10) -Glide you may not know the knowledge point
- Three party library source notes (11) -OkHttp source details
- Tripartite library source notes (12) -OkHttp/Retrofit development debugger
- Third party library source notes (13) – may be the first network Coil source analysis article
When using OkHttp or Retrofit, I think the most custom implementation that most developers do is the interceptor. Because OkHttp’s interceptors are so useful, many of our requirements — adding headers, calculating and adding signature information, logging network requests, etc. — can all be automated by interceptors, which can override global OkHttp network requests as long as rules are defined
As is my custom with the Tripartite Library Source Notes series, every article I write about the source explanation is followed by a custom implementation or extended reading of the tripartite library. This article will write about the actual content of OkHttp, to achieve a visual packet capture tool on the mobile side: Monitor
A, the Monitor
Monitor is suitable for projects that use OkHttp/Retrofit as a network request framework. Once the MonitorInterceptor is added, Monitor automatically records and saves all network request information and automatically displays it in a popover
The final effect is as follows:
Second, the realization of ideas
Here is a brief introduction to the implementation of Monitor
In fact, Monitor is an open source library THAT I wrote a long time ago. It just conforms to the topic of the article I am writing now, so I took the opportunity to do an overall refactoring and implement it entirely in Kotlin language. Please feel free to eat it. Its core idea is to get Request and Response through Interceptor, record each Request information, and store it in the database for persistent preservation. The implementation idea is similar to SquareUp official Ogging-Interceptor. Just that Monitor will be more direct and convenient 😋😋
The general framework of the Debug version of the MonitorInterceptor is shown below. HttpInformation is an entity encapsulation of request and response, and is the entity class that will eventually be stored in the database. Get request through chain, pre-occupy the local database, get response after proceed, parse the result of this request, save all information in HttpInformation and update the database, and pop-up Notification
/ * * * the author: leavesC * time: 2020/10/20 and * description: * GitHub:https://github.com/leavesC * /
class MonitorInterceptor(context: Context) : Interceptor {
@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
val httpInformation = HttpInformation()
processRequest(request, httpInformation)
httpInformation.id = insert(httpInformation)
val response: Response
try {
response = chain.proceed(request)
} catch (e: Throwable) {
httpInformation.error = e.toString()
throw e
} finally {
update(httpInformation)
}
processResponse(response, httpInformation)
update(httpInformation)
return response
}
private fun processRequest(request: Request, httpInformation: HttpInformation){...}private fun processResponse(response: Response, httpInformation: HttpInformation){...}private fun showNotification(httpInformation: HttpInformation){...}}Copy the code
The release Version of the MonitorInterceptor does nothing but simply forwards the request without any additional performance cost or reference
class MonitorInterceptor(context: Context) : Interceptor {
@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
return chain.proceed(request)
}
}
Copy the code
HttpInformation contains all the request parameters and return values for the request and response of a single network request. ResponseBody only stores the return values of text types (such as Json and XML) and does not store binary files such as images
class HttpInformation {
var url = ""
var host = ""
var path = ""
var scheme = ""
var protocol = ""
var method = ""
var requestHeaders = mutableListOf<HttpHeader>()
var responseHeaders = mutableListOf<HttpHeader>()
var requestBody = ""
var requestContentType = ""
var requestContentLength = 0L
var responseBody = ""
var responseContentType = ""
var responseContentLength = 0L
var requestDate = 0L
var responseDate = 0L
var responseTlsVersion = ""
var responseCipherSuite = ""
var responseCode = DEFAULT_RESPONSE_CODE
var responseMessage = ""
var error: String? = null
}
Copy the code
HttpInformation is stored in the Room database for persistence. I have to say that Jetpack’s Room and LiveData are very nice to use together, using LiveData as the database return value. It is very convenient to monitor data changes in the database in real time in observer mode
/ * * *@Author: leavesC
* @DateDavid: 2020/11/14 because *@Desc: * /
@Dao
interface MonitorHttpInformationDao {
@Query("SELECT * FROM monitor_httpInformation WHERE id =:id")
fun queryRecordObservable(id: Long): LiveData<HttpInformation>
@Query("SELECT * FROM monitor_httpInformation order by id desc limit :limit")
fun queryAllRecordObservable(limit: Int): LiveData<List<HttpInformation>>
@Query("SELECT * FROM monitor_httpInformation order by id desc")
fun queryAllRecordObservable(a): LiveData<List<HttpInformation>>
}
Copy the code
The UI layer does not have to worry about thread switching and memory leaks, but simply observes
private val monitorViewModel by lazy {
ViewModelProvider(this).get(MonitorViewModel::class.java).apply {
allRecordLiveData.observe(this@MonitorActivity, Observer {
monitorAdapter.setData(it)
})
}
}
Copy the code
3. Remote reference
I have released the code to the Jitpack so that you can use it directly remotely. Both debug and release dependencies are introduced. The release version of the MonitorInterceptor does not perform any operations, avoiding information leaks, and does not increase the Apk size
allprojects {
repositories {
maven { url 'https://jitpack.io' }
}
}
dependencies {
debugImplementation 'com. Making. LeavesC. Monitor: Monitor: 1.1.3'
releaseImplementation 'com. Making. LeavesC. Monitor: Monitor - no - op: 1.1.3'
}
Copy the code
Once you add a MonitorInterceptor to OkHttpClient, the rest of the action is done automatically
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(MonitorInterceptor(Context))
.build()
Copy the code
Fourth, making
The GitHub link is here: Monitor