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,RetrofitThe default implementation isOkHttpCall<T>, you can also customize as requiredCall<T>;
  • CallAdapter<T>Will:CallObject to other objects, such as to supportRxJavaObservableObject.

Retrofit is a process for making web requests:

  • throughRetrofitThe objects andMethodObject to obtaincallAdapter,responseTypeAs well asresponseConverterThree objects;
  • By parsingMethodThe annotations and a series of checks are performed to get the central managed objectServiceMethod;
  • throughServiceMethodObject gets what is actually executedCallObject to performHttpThe 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 overall design

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 youXSnowThe 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: retrieveGETMethod request object;
  • POST: getPOSTMethod request object;
  • HEAD: getHEADMethod request object;
  • PUT: getPUTMethod request object;
  • PATCH: getPATCHMethod request object;
  • OPTIONS: getOPTIONSMethod request object;
  • DELETE: getDELETEMethod 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 objectsLruCache, the cache algorithm is adoptedLruAlgorithm (Least Recently UsedLeast recently used algorithm), the cache size is 1/8 of the maximum memory.
  • Disk cache: Disk cacheKEYusingMD5Encryption, the cache duration can be customized. If there is no customization, the cache object is permanent storageDiskLruCacheSo is the caching algorithmLruThe 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_cacheDirectory, preferentially stored toSDCard, the default cache size is20M.
  • SharedPreferences storage:SharedPreferencesStorage is performed on cached objectsBase64Encrypted 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 eventsMapAnd common eventsSubject, also defines the fetchFlowableAnd delete sticky events and delete sticky eventsMapMethods.
  • 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 whichEventSubscriberAnd then you put them together and you getEventComposite.
  • ThreadMode: A thread model that includes threads such as the main thread, IO thread, etcgetScheduler(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 inActivityTo get aFragmentTo perform permission callback processing, provides a series of permission application methods, there are multiple permission to process callback alone or unified, respectivelyrequestEachrequestWay.
  • RxPermissionsFragment: Permission application callback processingFragment.

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!