current position:Home>Okhttp source code analysis of Android network framework
Okhttp source code analysis of Android network framework
2022-06-24 09:44:43【Cattle within yards】
okhttp Use
okhttp Is divided into Request Ask for something to do with response Respond to .
request Request body : every last HTTP Every request should contain a URL, One GET or POST Methods and Header Or other parameters , Of course, it can also contain data streams of specific content types .
response Response code : The response contains a reply code (200 On behalf of success ,404 The representative did not find ),Header And custom optional body.
Packaged okhttp Library and okhttp Use :
Basic request (GET POST)
GET
Request.Builder builder = new Request.Builder();
Request request = builder.get().url(url).build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException error) {
// Response failure
}
@Override
public void onResponse(Call call, Response response) throws IOException {
// Response successful
}
});
POST
RequestBody body = RequestBody.create(JSON, jsonObject.toString());
client.newCall(
new Request.Builder()
.url(url)
// .headers()// Add head
.post(body)
.build()).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
LogUtil.i("http response " + response);
if (response.isSuccessful()) {
}
}else {
}
}
});
okhttp Request flow and source code analysis
From the above request, we can see that synchronous and asynchronous , It's all through newCall() To achieve the , that newCall() What has been achieved ?
// Returned a Call object
override fun newCall(request: Request): Call = RealCall(this, request, forWebSocket = false)
Synchronization request call.execute()
override fun execute(): Response {
// First judge whether you have requested
check(executed.compareAndSet(false, true)) { "Already Executed" }
timeout.enter()
callStart()
try {
// Distributor for distribution
client.dispatcher.executed(this)
return getResponseWithInterceptorChain()// Walking interceptor
} finally {
client.dispatcher.finished(this)// Callback after completion
}
}
/** Used by [Call.execute] to signal it is in-flight. */
@Synchronized internal fun executed(call: RealCall) {
runningSyncCalls.add(call)// Go directly to the running synchronization queue to get values
}
Source code can be seen , Synchronous interceptor , Go directly to the executing synchronization queue to get the value .
Asynchronous requests
override fun enqueue(responseCallback: Callback) {
// First judge the current call Whether it has been implemented , Exception throwing was executed
check(executed.compareAndSet(false, true)) { "Already Executed" }
callStart()
client.dispatcher.enqueue(AsyncCall(responseCallback))// Asynchronous distribution
}
internal fun enqueue(call: AsyncCall) {
synchronized(this) {
readyAsyncCalls.add(call)// First put the task in the waiting queue
// Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to
// the same host.
if (!call.call.forWebSocket) {
val existingCall = findExistingCallWithHost(call.host)
if (existingCall != null) call.reuseCallsPerHostFrom(existingCall)
}
}
promoteAndExecute()
}
private fun promoteAndExecute(): Boolean {
this.assertThreadDoesntHoldLock()
val executableCalls = mutableListOf<AsyncCall>()
val isRunning: Boolean
synchronized(this) {
val i = readyAsyncCalls.iterator()
// Iterations wait to execute asynchronous requests
while (i.hasNext()) {
val asyncCall = i.next()
// Number of tasks executing asynchronous requests Not greater than 64 individual
if (runningAsyncCalls.size >= this.maxRequests) break // Max capacity.
// The same host Number of requests for Not greater than 5
if (asyncCall.callsPerHost.get() >= this.maxRequestsPerHost) continue // Host max capacity.
i.remove()
asyncCall.callsPerHost.incrementAndGet()
executableCalls.add(asyncCall) // A collection of tasks that need to be started , Create a temporary queue
runningAsyncCalls.add(asyncCall)// Put the task to be executed into the queue that is executing asynchronously
}
isRunning = runningCallsCount() > 0
}
// Process the tasks in the temporary queue , Iterative processing
for (i in 0 until executableCalls.size) {
val asyncCall = executableCalls[i]
asyncCall.executeOn(executorService)// Put it into the thread pool for processing
}
return isRunning
}
// Asynchronous processing task source code
override fun run() {
threadName("OkHttp ${redactedUrl()}") {
var signalledCallback = false
timeout.enter()
try {
// Perform the requested , Walking interceptor
val response = getResponseWithInterceptorChain()
signalledCallback = true
responseCallback.onResponse([email protected], response)
} catch (e: IOException) {
if (signalledCallback) {
// Do not signal the callback twice!
Platform.get().log("Callback failure for ${toLoggableString()}", Platform.INFO, e)
} else {
responseCallback.onFailure([email protected], e)
}
} catch (t: Throwable) {
cancel()
if (!signalledCallback) {
val canceledException = IOException("canceled due to $t")
canceledException.addSuppressed(t)
responseCallback.onFailure([email protected], canceledException)
}
throw t
} finally {
client.dispatcher.finished(this)// Callback after completion
}
}
}
/** Used by [Call.execute] to signal completion. */
internal fun finished(call: RealCall) {
finished(runningSyncCalls, call)
}
private fun <T> finished(calls: Deque<T>, call: T) {
val idleCallback: Runnable?
synchronized(this) {
if (!calls.remove(call)) throw AssertionError("Call wasn't in-flight!")
idleCallback = this.idleCallback
}
val isRunning = promoteAndExecute()// After completing this mission request , To make the next request
if (!isRunning && idleCallback != null) {
idleCallback.run()
}
}
As can be seen above ,RealCall There are three queues in the
1、 Executing synchronization queue
2、 Executing asynchronous queue
3、 Asynchronous queue ready for execution , A queue in which tasks are queued for preparation
Asynchronous request process :
1、enqueue() after , First judge whether the current task is executed , Distribution without distributor is not executed
2、 First put the task into the asynchronous queue waiting for execution readyAsyncCalls in
3、 Perform an iteration on the waiting queue , Judge whether the number of tasks being executed is greater than 64 , same host Is it greater than 5
4、 The number of tasks in the executing asynchronous queue is greater than 64, It cannot be executed , Continue waiting in the waiting queue , If the current mission is host>5, Then judge the execution of the next task
5、 Put the task to be executed into the task being executed , And put it in a temporary alignment , Call the thread pool to execute
6、 After thread pool execution , Walking interceptor , After completion , Let's go .
7、 The interceptor follows the chain of responsibility mode , The five interceptors execute , After completion , Callback .
8、 After completion , Re trigger promoteAndExecute(), Make the next task request
Five interceptors
1、RetryAndFolloeUpInterceptor: Retry the directional interceptor
Determine whether the user canceled the interceptor , After obtaining the results , Use the status code to determine whether redirection is needed , Restart all interceptors if conditions are met
2、BrisgeInterceptor: Bridge interceptor
Network processing after parameter transmission :Header, Body Handle , Automatically put HTTP agreement , Request header ,,GZIP Compress , Wait for the treatment , preservation cookie Interface to handle
3、CacheInterceptor: Cache interceptor
Request a resource that will not change , Before reading, judge whether there is a current cache , If there is a cache, call the cache and call back directly , No, , Take the connection interceptor
4、Connection: Connection interceptor
Cache miss , Take the connection interceptor , Find the connection to the server , Or create a connection , Get the corresponding socket flow , No additional processing after obtaining the results , Go straight to the request service interceptor
5、CallServerInterceptor: Request service interceptor
When you get the connector , Package data in class Send it to the server , Get a response , Communicate with the server , Send data to the server , Parse the response data read , Go back step by step
The chain of responsibility model
Similar to recursive call , From top to bottom , After execution , The result returns from bottom to top .
Finally, in order to help everyone learn effectively Android Top 100 framework knowledge points , Specially arranged a Android 100 frames for advanced urination , Help everyone further on the road of Technology , There's something you need You can reply to me by private mail in the background 666 Ready to pick up !!!
copyright notice
author[Cattle within yards],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2022/175/202206240822498385.html
The sidebar is recommended
- Fasthttp: go framework ten times faster than net/http (server)
- The difference between preload and prefetch and how to optimize in webpack projects
- Several ways of calling methods to transfer parameters in react render
- Axios usage
- LabVIEW finds prime numbers in an array of n elements
- Elementui form custom regular expression validation text box
- Export markdown to HTML, PDF with browser
- Experience summary of typescript transformation process of old vue2.x projects
- Front end development uses graphql -- vue3 uses graphql
- JS to get the last element of the array
guess what you like
About Axios request - delete method
The salon for the first anniversary of the open source of oasis, an ant interactive graphics engine, is coming. On February 26, we will see you in the live studio!
Best practices for cookie notification
How does HTML5 implement live streaming? It's worth learning!
Record webpackdemo configuration
Android studio uses iconfont Ali vector icon library
HttpMediaTypeNotSupportedException: Content type ‘application. yml/json; charset=UTF-8‘ not supported
CSS notes
Nginx enables geoip2 module to realize national city identification - the road to dream
Database to query the quantity of books lent in this month. If it is higher than 10, it will display "more than 10 books lent in this month". Otherwise, it will display "less than 10 books lent in this month"
Random recommended
- Baidu map API User Guide - Javascript API | JavaScript API GL | JavaScript API Lite
- [javascript question brushing] tree - verify binary search tree, leetcode 98
- JavaScript gets the current date() and converts it to mm / DD / yyyy, June 23, 2022
- Explanation of HTTP network protocol
- Vue3+vite3 to develop Netease cloud music Day1 backend environment
- You can't even tell how nginx forwarded the request to you. It's good to say that you're not a crud Engineer?
- Baidu map JavaScript API, the earth mode is always similar to the "night mode", solve!
- Vue- different interfaces after different roles log in
- Bugatti launched a two wheeled scooter with less than 1000 US dollars
- The publishing function written by Vue (the simple version of wechat applet cooperates with cloud data development), pictures can be submitted, words can only be printed, but not submitted (self-improvement submission)
- Front end export excel, JS xlsx export
- Wed, front-end Personal Learning Websites
- The project cannot run after webpack installation
- Webpack dev server cannot start normally cannot find module 'webpack / bin / config yargs‘
- Ajax request request plug-in on uniapp for its own use
- Determine whether a function exists in JavaScript - function_ exists
- [bug] @jsonformat has a problem that the date is less than one day when it is used
- Vue/js operation DOM full screen switch, full screen open dom requestFullscreen();
- [angular] angular removes the input spaces. The angular user-defined attribute instruction - prohibits the input box from entering spaces - and deletes the spaces in the copied content (with other solutions attached)
- Cruise is now charging for its driverless ride service in San Francisco
- Principles of vue3 compiler
- Reactiveeffect principle of vue3
- Patch update details for vue3
- Nexttick principle of vue3
- Pyqt5 how to make windows borderless and movable by dynamically loading the UI?
- How to open an account online for new bonds? Please bless me
- React usestate storage function
- CSS problem, card jitter
- () is a linear table that restricts the internal structure of data elements to only one character. A. Stack B. queue C. string D. array
- Reactnative 0.69 release
- The new design can be called a new generation. The gradient borderless grille has a high appearance value. The application drawing of Changan Ruicheng plus
- Render external link address URL video page via iframe - Vue
- Vue failed to parse source for import analysis because the content contains invalid JS syntax
- Differences between front-end set and map
- Difference between front-end foreach and map
- Front end array flattening
- How the front end judges the data type
- Front end CSS style expand and collapse
- Front end array de duplication
- Front end throttling and anti shake