preface
Due to the use of friends mentioned XSnow framework information is a bit large, I hope there will be an article to introduce the details of each module in the framework, so this article will be around the framework of each module of the relevant ideas and important technical points to do a detailed analysis, so that the use of the framework of friends have a clear understanding of XSnow.
To prepare
Because XSnow framework is based on RxJava2 and Retrofit2 to build, which also relies on such as network base library OkHttp, picture loading library Glide, database base library GreenDao, so the use of this project friends need to have a basic understanding of these several basic frameworks, A brief explanation of these frameworks is provided below.
RxJava
Familiar friends may know that the framework is a member of the ReactiveX programming library, which is a new programming idea, generally called reactive programming idea, for the use of this idea is not described here, interested friends can look at the article ReactiveX document Chinese translation.
RxJava main pattern is the observer pattern, what is the observer pattern, can be simply interpreted as: two objects, the observer &observed which establish the relationship between the subscription observer &observed, if the observer has changed, you will need to promptly notify the observer observer after receiving the notice to make corresponding processing. The description can get a little convoluted, but let’s give a simple example, for example: Customers to buy a cake such a scenario, the customer and the cake shop clerk, respectively) as an observer &observed, because the cake is now do take time to complete, customers tend to pay first when buy the clerk to get a proof of payment after leave to busy other things, so they will set up the relationship between the purchase (subscription relationship), After the clerk finishes the cake (the observed changes), the clerk will inform the customer to pick it up (the message will be notified to the observer), and the customer will come to pick up the cake after receiving the notice from the clerk (the observer will make corresponding treatment after receiving the notice). Here, a complete observer mode on the end of the scene, I hope to help friends deepen the understanding of the observer mode.
Continue to explain the understanding of RxJava below, first to imagine such a scene, a universal machine, it can produce anything, it has an input and an output terminal, there are many among the core components, such as converter, transfer, etc., they all external is hidden, but outside there is a control terminal, can input any desired rules, The machine sends the input to the output according to the rules set by the terminal. RxJava is such a universal machine, it has data input side, data output side, there are also a lot of rules in the middle of the manipulation of data, such as various operators, thread transformation, they all have a purpose, is how to make the data source through a certain rule output.
The above explanation is just to give you a clear understanding of RxJava, not involved in the specific technical details, if you want to understand the details of the RxJava2.0 tutorial for beginners, this is a series, after reading these articles, you can use RxJava to do some basic functions. This series is about RxJava2. If you want to learn about the first version of RxJava and see what has changed between the two versions, you can check out RxJava2 for Android developers and RxJava2 vs RxJava1.
Retrofit
Retrofit is simply a RESTful API request tool based on OkHttp. RESTful is an architectural style that is characterized by resources, unified interfaces, URIs, and statelessness. For a more detailed overview of RESTful architectural styles, see the RESTful Architecture Style Overview.
Retrofit actually acts as an Adapter when used, essentially translating a Java interface into an HTTP request object and sending the request using OkHttp. The core idea is dynamic proxy, which is when you call a Class’s methods before or after you insert the code you want to execute. Generally speaking, you need to perform some operations before and after an operation. For example, you need to check whether the user has logged in before viewing the user’s personal information, and you want to clear the user’s access records after the user accesses the database.
Retrofit’s design is very plug-in and lightweight, highly cohesive and low coupled. Retrofit basically defines four interfaces:
Callback<T>
: Request the return of data;Converter<F, T>
: Parses returned data, usually usedGSON
;Call<T>
: Send a request,Retrofit
The default implementation isOkHttpCall<T>
, you can also customize as requiredCall<T>
;CallAdapter<T>
Will:Call
Object to other objects, such as to supportRxJava
的Observable
Object.
Retrofit is a process for making web requests:
- through
Retrofit
The objects andMethod
Object to obtaincallAdapter
,responseType
As well asresponseConverter
Three objects; - By parsing
Method
The annotations and a series of checks are performed to get the central managed objectServiceMethod
; - through
ServiceMethod
Object gets what is actually executedCall
Object to performHttp
The request.
The above is just an explanation of the core functions of Retrofit. If you want to learn more about Retrofit, take off the Wheel: Take Off Retrofit
OkHttp
OkHttp is an efficient HTTP library. The overall design of OkHttp is as follows (image source: Web days) :
OkHttp requests are managed in facade mode by OkHttpClient, which owns all the configuration and parameters of the sub-modules and distributes the requests to the corresponding subsystems. It consists of the following core subsystems: routing, connection protocol, interceptor, proxy, security authentication, connection pooling, and network adaptation. The Dispatcher is used to retrieve requests (calls) from the RequestQueue, to obtain an interface based on whether the Cache or Network has been called, and then to retrieve the requested data from the in-memory Cache or the server. The engine has synchronous and asynchronous requests. Synchronous requests directly return the current Response via call.execute (), while asynchronous requests add the current AsyncCall call.enqueue to the request queue and retrieve the result via Callback.
The Interceptor approach in OkHttp provides a great help in the overall design. It adopts the chain of responsibility mode. It is not only responsible for intercepting requests for additional processing (such as adding headers), but actually integrates the actual network request, caching, transparent compression, and other functions. Each function is just an Interceptor, which is then connected into an interceptor. Chain, which completes a network request.
If you want to learn more about OkHttp, you can take a look at the Dismantling of wheels series: Dismantling OkHttp.
Glide
Glide. With (this).load(URL).into(imageView); I’m done loading the image. Use is very simple, if you want to understand in detail, here recommend Guo Lin Glide source code analysis, Android picture loading framework the most complete analysis, this is a series, after reading for Glide basic can know how to use and why to use so.
GreenDao
GreenDao is a lightweight and fast ORM solution for mapping objects to SQLite databases. If you want to learn more about GreenDao, check out GreenDao 3.0 for Android Data Store.
Note:
- The above explanation of the basic library is just a brief introduction to let you
XSnow
The framework uses the relevant technology has an intuitive feeling, if you want to understand in detail, above in each base library behind the remarks of the personal think better article, can be used as a reference to learn the framework. - The following descriptions use the package name as the title of each module, which also indicates that modules are fully decoupled from each other and makes it easier for readers to understand the code and analyze it logically.
Http (network module, including network request, upload and download)
This module is the core function of XSnow framework, its core idea is to separate the request and based on dynamic configuration, using the facade mode, the upper layer does not have to do with the specific implementation details, just need to configure the relevant request information can achieve a complete network request function. This module has a large amount of code compared to other modules, and each package under this module will be dissected and explained in detail. Now let’s first take a look at the ViseHttp class, which is equivalent to the facade class of this module and also the unique entry class of network requests. All requests are constructed by this class, such as:
- BASE: the custom request object is passed in to facilitate the external to customize the request according to their own requirements.
- GET: retrieve
GET
Method request object; - POST: get
POST
Method request object; - HEAD: get
HEAD
Method request object; - PUT: get
PUT
Method request object; - PATCH: get
PATCH
Method request object; - OPTIONS: get
OPTIONS
Method request object; - DELETE: get
DELETE
Method request object; - UPLOAD: get file UPLOAD request object, support incoming call;
- DOWNLOAD: Obtains the file DOWNLOAD request object.
This class also provides the ability to interrupt a single network request by tag and all network requests, as well as the ability to delete the cache by key and clear all network caches. It is important to note that the class’s initialization method must be called when the initialization is applied
ViseHttp.init(this);Copy the code
And associated network configuration
Visehttp.config () // configure the requested host address.baseurl ("http://10.8.4.39/"GlobalHeaders (new HashMap<String, String>()) // Configure the global request headers. String>()) // configure the readTimeout duration, in second.readtimeout (30) // configure the writeTimeout duration, in second.writetimeout (30) // configure the connection timeout duration, in second.writetimeout (30) // configure the connection timeout duration, in second.writetimeout (30) // configure the connection timeout duration, in second. ConnectTimeout (30) // Sets the retry times for failed requests. RetryCount (3) // Sets the retry interval for failed requests, in milliseconds. RetryDelayMillis (1000)...... ;Copy the code
In this way, relevant network request functions can be invoked in the application. If not initialized, the module will throw the following exception when calling a network request:
Please call ViseHttp.init(this) in Application to initialize!Copy the code
Remember that!
Here are the functions of each package in this module:
-
API This package provides the REQUEST API. Currently, there is only one class, ApiService, which mainly provides the request method for Retrofit to make network requests.
-
Body that package is provided by the relevant request and response body, only a request to upload progress show entity class UploadProgressRequestBody, by passing in UCallback back to deal with the progress of the upload file.
-
Callback This package provides the related callback classes and currently contains the upstream callback UCallback and the request API callback ACallback.
-
Config This package provides configuration-related classes. Currently, only the request global configuration class HttpGlobalConfig provides rich configuration methods. The purpose of this class is to separate configuration from request.
-
Core The package provides some core function classes, including the cache processing class ApiCache, Cookie management class ApiCookie, and network request subscription management class ApiManager. The cache adopts disk caching and supports various cache policies. The strategies are described in the Strategy package. Cookies are stored in SharedPreferences, and storage objects are saved in hexadecimal.
-
Exception this package provides network request-related exception classes, and currently provides a unified request exception handling class, ApiException, which can be used to determine the cause of a failed request.
-
Func This package provides data conversion classes, currently including ApiFunc
classes that convert ResponseBody objects to T and Observable
observables
class ApiRetryFunc. The ApiRetryFunc class deals primarily with the network timeout retry mechanism, passing in the number of retries and the time between retries, which can be configured in the configuration class.
-
Interceptor This package provides a series of interceptor classes. It is also the core package of this module. Most of the basic functions can be provided in the way of interceptor. HeadersInterceptor: Request header interceptor; Httplogtor: Http log print interceptor; NoCacheInterceptor: NoCacheInterceptor; OfflineCacheInterceptor: OfflineCacheInterceptor; OnlineCacheInterceptor: OnlineCacheInterceptor; 7, UploadProgressInterceptor: upload a file to show progress.
-
Mode This package provides the related entity classes.
-
BaseRequest
provides a BaseRequest class that writes R as the actual request class. BaseRequest
In this way, the object of the corresponding request class can be obtained to configure the related request information. If the request configuration conflicts with the global configuration, the request configuration takes precedence, which means that the local request configuration replaces the same global configuration. The request class provides a series of request header configuration, request parameter configuration and other information. If it is a POST request, it also provides the way to upload JSON string, upload form and so on. If it is a file, it provides the way to add file, add byte array and add stream. CacheExecute and execute are distinguished because cacheExecute and no cacheExecute requests return different results and therefore need to be processed separately.
-
Strategy CacheAndRemoteStrategy provides cache-related policies, including the following: 1. CacheAndRemoteStrategy: Loads cached data before loading network data; FirstCacheStrategy: Load cached data first; 3. FirstRemoteStrategy: Give priority to loading network data; OnlyCacheStrategy: only cache data is loaded; OnlyRemoteStrategy: Load only network data. The cache strategy adopts the principle of interface oriented programming, defines a cache strategy interface ICacheStrategy
, and assigns the specific implementation of the policy to each subclass.
-
Subscriber This package provides the relevant subscribers, The current unified subscriber ApiSubscriber
contains the API request, the subscriber ApiCallbackSubscriber
contains the callback, and the subscriber DownCallbackSubscriber
contains the download callback.
Cache
The module provides several caching methods, namely memory caching, disk caching and SharedPreferences storage. The main idea of this module is interface oriented programming, provides the ICache interface, mainly includes the ability to add cache, obtain cache, delete cache, clear all cache and determine whether to include the cache. Each caching method is explained in detail below:
- Memory cache: Memory cache uses singleton mode to manage cache objects
LruCache
, the cache algorithm is adoptedLru
Algorithm (Least Recently Used
Least recently used algorithm), the cache size is 1/8 of the maximum memory. - Disk cache: Disk cache
KEY
usingMD5
Encryption, the cache duration can be customized. If there is no customization, the cache object is permanent storageDiskLruCache
So is the caching algorithmLru
The algorithm, cache location, and cache size can be customized. If not, the default value is used. The default cache location is in the application cache directorydisk_cache
Directory, preferentially stored toSD
Card, the default cache size is20M
. - SharedPreferences storage:
SharedPreferences
Storage is performed on cached objectsBase64
Encrypted storage, you can customize the cache file name, if not customize the default file namesp_cache
.
Event (Event bus)
This module uses Rx to realize RxBus function, and its Bus design is similar to EventBus. It is mainly composed of the following core classes:
- EventBase: Base class for event handling, containing sticky events
Map
And common eventsSubject
, also defines the fetchFlowable
And delete sticky events and delete sticky eventsMap
Methods. - EventComposite: an EventComposite class that combines all the events in a class that needs to receive an event and provides a method for sending sticky events.
- EventSubscriber: an EventSubscriber that provides the means to subscribe to events and distribute them.
- EventFind: Finds event receiving methods based on annotations, from which
EventSubscriber
And then you put them together and you getEventComposite
. - ThreadMode: A thread model that includes threads such as the main thread, IO thread, etc
getScheduler(ThreadMode thread)
To get the thread scheduler.
Event receiving is managed by annotation mode class. After the event subscription, the corresponding event receiving place can be found according to the annotation.
In order to unify the event bus, the module defines the IBus interface and provides the following four methods:
void register(Object object);
void unregister(Object object);
void post(IEvent event);
void postSticky(IEvent event);Copy the code
IEvent interface is also provided, and all events implement this interface, so that specific event implementation classes can be separated. In fact, interface oriented programming is also provided.
The module also provides the idea of plug-ins. The upper layer can inject implementation classes such as EventBus into the module, and then the event processing will follow the strategy implemented by EventBus. However, there is a problem here. Therefore, the annotation event still needs to be replaced in a unified way. The coupling is too high, and no better way has been found at present. If any friend has a good way to decouple, welcome to leave a message!
Loader (image loading)
The module for the picture loading to do the second packaging, interface programming, each implementation is a picture loading strategy, the default use Glide picture loading framework, the upper layer can also be customized interface ILoader, For example, the Fresco image framework implementation class, FrescoLoader, provided in the Demo, has the main idea of being plug-in and externally injecting any loading strategy to achieve high cohesion and low coupling.
The interface provides the following four ways to load images:
- Loading network images
void loadNet(ImageView target, String url, Options options);Copy the code
- Loading resource images
void loadResource(ImageView target, int resId, Options options);Copy the code
- Load an image from Assets
void loadAssets(ImageView target, String assetName, Options options);Copy the code
- Loading local images
void loadFile(ImageView target, File file, Options options);Copy the code
If GlideLoader is used, it is necessary to compile this dependency. If GlideLoader is used, it is necessary to compile this dependency. GlideLoader also adds the following authentication mechanism during initialization
try {
Class.forName("com.bumptech.glide.Glide");
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Must be dependencies Glide!");
}Copy the code
An exception is thrown if the Glide library is not relied on.
Database (Database)
This module takes GreenDao as the underlying database and defines the operation interface of the database IDatabase
, which is managed by the DBManager
abstract class uniformly. Since the Dao corresponding to each entity class is different, So the abstract method getAbstractDao() is defined. Due to the particularity of GreenDao, the implementation class of this method cannot be set up in the framework. All database operations can refer to DbHeDlper class in Demo to implement its own database operation management class, and different DAOs can implement the corresponding getAbstractDao() method.
Permission (Permission management)
The module uses Rx thought unified management permission application, one line of code to solve the permission application problem.
PermissionManager.instance().with(this).request(onPermissionCallback, Manifest.permission.CALL_PHONE);Copy the code
This module is very succinct, just a few classes, they are described below:
- OnPermissionCallback: Permission request callback interface to invoke specific business logic in the interface implementation class.
- Permission: Permission entity class that contains the Permission name, whether the Permission is granted, and whether the Permission request justification variable is displayed.
-
PermissionManager: Permission management class, which is also the only entry for permission application, adopts singleton mode. You need to pass in the current Activity object through with, and call the request method to apply for permission. You need to pass in callback and permission list, and the permission list is passed in by variable array.
PermissionManager.instance().with(this).request(new OnPermissionCallback() { @Override public void onRequestAllow(String permissionName) { DialogUtil.showTips(mContext, getString(R.string.permission_control), getString(R.string.permission_allow) + "\n" + permissionName); } @Override public void onRequestRefuse(String permissionName) { DialogUtil.showTips(mContext, getString(R.string.permission_control), getString(R.string.permission_refuse) + "\n" + permissionName); } @Override public void onRequestNoAsk(String permissionName) { DialogUtil.showTips(mContext, getString(R.string.permission_control), getString(R.string.permission_noAsk) + "\n" + permissionName); } }, Manifest.permission.CALL_PHONE);Copy the code
- RxPermissions: Permission management core class, which is passed in
Activity
To get aFragment
To perform permission callback processing, provides a series of permission application methods, there are multiple permission to process callback alone or unified, respectivelyrequestEach
和request
Way. - RxPermissionsFragment: Permission application callback processing
Fragment
.
UI (UI module, including universal adapter, view switch)
This module contains the universal adapter and the attempt to switch function. The adapter uses the ViewHolder to manage the loading and presentation of data, separating the data from the presentation, providing the DataHelper interface to load data, and the ViewHelper interface to handle the PRESENTATION of UI. The HelperAdapter provides the common methods of the adapter, which can basically meet the common requirements of the adapter. View switching is managed by StatusLayoutManager, and views are displayed and processed by importing related configurations. Internal provides OnRetryListener retry listener and OnStatusViewListener attempt to switch listener, and defines a custom view StatusLayout to display the following five views:
- CONTENT: CONTENT view;
- LOADING: LOADING a view.
- EMPTY: EMPTY view;
- NETWORK_ERROR: network error view.
- OTHER_ERROR: indicates other error views.
The last
To this, XSnow framework all modules are introduced, I do not know whether friends have a deeper understanding of the framework.
Described above some parts might explain is simpler, this is because some of the module itself is not very complicated, so I didn’t do too much, if you want to be more clear understanding of the framework, is the best way to observe directly down the source code, if you have any where in the process of looking at the source don’t understand or think of implementation has a problem and you have a better plan can leave a message!
Source code address: github.com/xiaoyaoyou1… , source address provides a detailed use of the document, there are versions of the introduction and QQ group information, if you like the framework might as well little star and share to the side of friends, let more friends to participate, thank you!