Uploading and downloading are most
APP essential of functionalities, Showing progress bars also improves the user experience of essential link, definitely act as Configurable Integration Framework MVPArms of authors, I want to raise the developers again. of use Experience and development efficiency, Then I must provide a solution.
So I opened it.
Github easy of Searching around with Retrofit , Okhttp , Glide concern of Progress Listening Library, There's a lot of library., But none of them are where I want them to be. of need, So I rolled up my sleeves., Ready to jerk one off., definitely, Before you start jerking off, you have to briefly sort yourself out of need this one The library must support multiple platforms, Okhttp , Retrofit , Glide All three must be supported at the same time Although these three libraries are supported, the library does not contain these three libraries, let the user to introduce their own, reduce the size of the library use It has to be simple.!!!, It's better to get it done in one line of code Less invasive, It is not necessary to change the previously written of Network request code, introduce conflict with introduce this one warehouse, right before of None of the code can have any effect low coupling, user makes a network request of code, Mustn't. harmony Progress receiving end of The code has too many connections (located) at App of Any location can receive a certain network request of Progress information Not only do we need to satisfy the one-to-one relationship of one data source for one progress receiver, but we also need to satisfy the one-to-many relationship of one data source for multiple progress receivers, so that we can synchronize the progress bars of multiple different locations Runs in the main thread by default, so users don't have to switch threads Needs analysis and research
pleasurable! all of a sudden, Writing out so many needs, When product managers even One word.!
The 8 requirements are very confusing. Except for the last one, which I know can be used
Handler come true, No other ideas at all., all right!, act as A quality young man I have to know what to expect, Let's start the analysis with the first requirement! Requirement 1 (multi-platform support)
Turn before you write have a look at
Google Found, Okhttp It is not difficult to implement upload and download progress monitoring, just rewrite RequestBody harmony ResponseBody , in conjunction with Interceptor The original of each request of RequestBody harmony ResponseBody Replace, it can be achieved, are template code, copy and paste on it, and Retrofit The underlying layer is used Okhttp , then you can do the same for the progress listener But how does Glide implement progress monitoring? me of first response even since Retrofit use Okhttp Requesting a network can then be very easy of realize, that will Glide The underlying request framework is replaced with the Okhttp It's also possible to implement, as such an awesome library, there must be a way to extend it, so I immediately went to the Glide of source code (computing), Stamped himself of think of a way (to do sth), find that Glide The underlying layer is the use of HttpConenction to request the network, and this class is replaceable, hurry up! Google have a look at compile 'com.github.bumptech.glide:okhttp3-integration:x.y.z@aar'
ok, found the solution, using the library provided above, replacing the underlying request framework with
Okhttp , this one Framework at its core of Localities have found ways to implement, It is mainly through Okhttp It's a relief. Demand 2 ( reduce the volume)
this one need
Google It's very simple, too, with provided Dependency framework, Dependence on packing of The frame will not be included Requirement 3 ( One line of code implements)
For this external
Api design-wise of need, We should have the main function implemented, And then slowly optimize to the point where you want to reach of Target so first analyze the following of need Requirements 4 ( Less invasive)
As mentioned in Requirement 1, the key to upload and download progress listening is in the
Interceptor in each request will be the original RequestBody harmony ResponseBody Replace with the rewritten How do I identify requests that need to be listened to for progress?
Replacement is simple, But not every request needs to be listened to upload harmony Download Progress, You can't replace every request., At first I thought. of is for those who need to listen to the progress of Request to generate a markers, then (afterwards) (located) at
Interceptor in parse to this one markers, would indicate that this one Requests need to listen for upload or download progress, Then we'll start replacing it.
So I thought of the simplest of way even (located) at requesting of When adding a custom of
Header , This eliminates the need to define additional of kind, Interceptor Traversing all Header find that there are this one customizable Header , you can replace
But then... It didn't solve Requirements 4, owing to This gives the user one more action than usual when requesting, If one wants to make the previous of Code with progress listening, We have to change them one by one., Increased workload, moreover this one The operation is directed at me this one library of, When the user does not want to use this one warehouse of length of time, It would involve modifying the previous of code, This still adds intrusiveness
Url as marker
A thought struck me. What more do you need to mark,
Url is the only of, No, you can't. act as markers (question tag)!!! Requirement 5 (low coupling), Requirement 6 (any location can receive), and Requirement 7 (one-to-many) Borrowing EventBus Ideas
Why do I put these three needs together, because they remind me of
EventBus , Multiple Observers use the same markers Register yourself into a container, person being observed use this one markers Post an events, Then from this one container in Take out all the use this one markers registered of observer, Notify one by one, This decouples both the, And just know that this one markers, (located) at App Any position can be listened to, also support one-to-many
add into Requirements 4, in refer to of use
Url act as markers, Then I can do what I requested before. of No need to change a single piece of code, Use only write receivers of The code can be implemented to listen to the progress of need Ideation Api
Since we're talking about
EventBus I'll use... EventBus of Api The user uses one line of code to pass in a markers and a events You can listen to the progress of uploads and downloads, yes markers even Url , events even Used to obtain Progress information of listener That's good enough. Requirement 3 of One line of code implements of need Like this ProgressManager.post( markers, events);
After the user calls this line of code, I'll put the
Url act as Key, listener act as value Put in a globally unique of Map in
wait a minute!? We agreed on one to many. of this (Cantonese)? consequently this one
value Must be List< listener > , This satisfies the one-to-many of Conditions. How are listeners notified internally?
We put all the
Url of listener It's all registered. this one container, Then when shall we inform? listener The progress information, of course, is in the RequestBody harmony ResponseBody in Start writing or reading a binary stream of length of time, owing to Only they're the first to know., retrieve harmony write of times, current (located) at Just put the corresponding Url of all listener Put in his Body in That's it
Requirements 4 As mentioned in the article, we don't know which requests need to listen to the upload or download progress and which don't, but now we can use the Url to identify, as we can in Interceptor Get it in. Request of Url
Previously we have included
Url act as Key registered into the container, if the container inside Contain this one Url that even illustrate this one requesting, is required to monitor upload or download progress of, Then we'll give it to him Replace with the rewritten Body and pass the listener in, the rewritten Body (located) at A binary stream occurs of retrieve or write constantly of traverse this one Url of all listener ,call listener method, and pass in the progress information, you can execute the user's update logic, and that's it! Requirement 8 (main thread execution)
this one Very simple, use
Handler.post(Runnable) (located) at Runnable in invoke listener The way it was done will be fine Framework detail optimization No manual logout required
We all know that.
EventBus After registering the observer, (located) at There is no need to accept it events time, You need to sign out manually, But apply it to me this one warehouse in, events of Reception may not need to be so rigorous So... In order to avoid use redundant of steps, me even use WeakHashMap Replaces the previous Map container, this one WeakHashMap will be in Java Virtual Machine When recycling memory, Find the one that hasn't been use of Key, Remove this entry as a whole So... No manual work is required remove() lock up
As mentioned above, the user only needs one line of code, which will
Url harmony listener Join the container, But this line of code, It could be (located) at Different threads in Is called of, And this line of code of some logic (located) at Multithreaded in is not safe of, All of this time I need to join the thread lock, this one It is important for the tripartite library, owing to You can't predict some users of operate toward use throw clear of mistake
Because I'm in
Demand 2 This library will only be used with the provided introduce Okhttp So... Okhttp Is not going to be scored aar package, so if the user has not introduced the Okhttp Yes, it will report. NoClassDefFoundError This error, however, will make the user unaware of the real cause of the error and make the user think it is caused by the library, so I will initialize the library, Class.forName("okhttp3.OkHttpClient"); If you can't find it Okhttp of this one kind, illustrate use No, I don't introduce Okhttp I'll throw out a very clear explanation of the error. Improving performance
owing to It mentions me above will be in
Body , When you start reading or writing to a binary stream, constant of Traversing all listener and call it of Listening methods, to achieve one-to-many of Synchronized updates
listener Performance problems occur when a certain number of listeners are reached, and when traversing, the user may add new listeners, and changing the length of the container during traversal is error-prone.
So I'm going to be a little more careful in putting
List transmitted inwards Body time, will this one List.toArray() If the array is allocated a continuous memory area and the length is fixed, so the indexing efficiency has the advantage, then use the array to traverse, because the length of the array is fixed, so there is no problem of length change when traversing Distinguish between multiple progressions of the same Url
App Users may (located) at The previous progress has not been uploaded or downloaded of case, Go on use the same Url Start a new one of requesting, If the framework use he who (located) at The upper layer does not do to remove duplicate clicks of operate, That's the same one Url will coexist (located) at Multiple positives (located) at execute of Progress updates, An identifier is required to distinguish which one Progress information( this one Url of all correct (located) at execute of Progress updates are called before this one Url registered of listener) So... me (located) at Body , which will be created with the System.currentTimeMillis() act as sole ID , Save it, Each time will Progress information harmony Id Pass it on together use he who conclude
In fact this one The library was already relatively simple, realize of Core Approach (located) at There are many places where you can copy and paste into of, But after I've encapsulated it, it's still better than before. of way, Simple and elegant., And writing this article of I also want to share it, How to analyze requirements, and how to package optimization for a small one of warehouse, Of course, usually also want to read more source code, Constantly accumulating harmony Learn from excellence of thought (located) at Inspiration comes from the moment you create, Like me this one warehouse even Reference of
EventBus of thought, (located) at When writing code, dare to think that you dare to try differently than before of New ideas, will continue to improve
The exact implementation still depends on the source code doesn't it? Remember to give Star ✊ Thanks!
Hello My name is Jessyan, if you like my articles, you can follow me on the following platforms
-- The end
1、定时器 2、BiologicalClassification 3、Is it surprising that there are so many people who dont have bank accounts Kora is here with a blockchain technology solution 4、Moving tile to kvm architecture or ovz architecture
5、9 Technical Architectures for High Performance Availability and High Concurrency