Android Architecture ... What is the clear way?
Objective
We know that it is complex and difficult to write quality software: It is not just about satisfying all the needs, but it should also be robust, maintainable, easy to test, and very flexible (flexible to change content, such as module addition and subtraction). A clear architecture (the clean Architecture) is born out of this need and can be a good choice in the software development process.
The idea of a refreshing architecture is simple: it represents a set of rules that can produce the following systems:
- Not relevant to the framework
- Easy to test
- UI-Independent
- Not related to database
- Independent of other external components
In the actual application process, there is no need to be divided as in the diagram, because it is only a schematic diagram. But one-way dependencies should be done: The code's dependencies can only be inward, and all internal modules should not know about any external modules, let alone any calls.
Here are some related words to help understand:
- Instances (Entities): These are business instances (Object) in the software implementation process.
- Data interaction (use Cases, also known as interactor): The data Interaction is responsible for reconciling the data transfer of the instance.
- Interface Adapter (Interface adapters): The interface adapter is responsible for data transformation, parsing data that is passed from the instance and the data interface . Presenter and controllers belong here. (It can be understood from the original text, in the design of usecase and entities, as far as possible to make these two layers of data simple, easy to use, improve the efficiency of these two layers.) In this way, the workload in the deeper layers becomes less. Just a personal understanding. )
- Frameworks and drivers (frameworks and Drivers): This section is responsible for all the relevant details, such as: UI, tools, frameworks, etc. (this is not understood here for the time being).
A clearer understanding is needed to see the video in the link through the wall.
Android architecture
The purpose of the architecture is to separate the principle that the internal business logic is completely extraneous to the outside, so that no external dependencies need to be loaded in the test.
To achieve this goal, I recommend dividing the program into three layers, each of which has its own work and is isolated from the other layers during the run.
It is worth mentioning that each layer can be independent by building its own data model for each layer. (in the code you'll find that you need to use data mapper to convert, as a cost, your model will span the entire app.) )
Diagram of the above content:
Note: I did not use any external libraries (except Gson to parse JSON data, and Junit,mockito,robolectric,espresso to test). In this way, I can make the example more clear. However, never go back to writing a wheel and take it from someone else (you have to pick it up).
Presentation layers (Presentation layer)
The logic associated with page logic and page animations is in this layer. It mainly uses the MVP architecture. You can also use MVC,MVVM and so on as needed. It is worth emphasizing that in the presentation layer, fragment and activity are simply view, without any logic other than the UI logic, and the rendering is implemented at this level.
Presenter works in this layer with the data interface (Interactor,use case) in a new thread (outside the UI thread), and then passes the data that needs to be presented to the view through a callback function.
Logical layer (Domain layer)
The business rules for this layer are: all logic occurs at this level. At the project level, you will find that all data interactions are implemented at this level.
This layer is a pure Java module and does not include any reliance on Android. All out-of-layer components interact with an instance (Object) in the logical layer through an interface.
Data layer
The data layer is like a warehouse, and all the data required by the app is fetched through the warehouse interface (Repository interface) located in the logical layer. This interface uses the warehouse model, i.e., to pick up a variety of data up and down through a factory, on demand. For example, when the user is obtained by ID, the program will determine if there are user data in the cache, if not, get from the server, and exist locally, if any, directly from the cache.
The reason for this is that users don't care what the source of the data is, they only care about whether the data is being retrieved.
Note: There is a simple example of this interface in the code. Or that sentence, do not re-do the wheel.
Error handling
My strategy is to use callback functions, so, for example, in a data warehouse, there will be two callback functions, Onresponse () and onerror (). The latter will package the exception into a wrapper class called "Errorbundle": This approach poses a certain problem, because it produces a series of layers of escalated callback functions that pass through the presentation layer and are disposed of by the presentation layer. This approach reduces code readability to some extent.
Another way is that I can implement Eventbus, and each time an error occurs, Eventbus will assign the time to the specified handler function. But this needs to be very rigorous, careful treatment, otherwise it will not be good management.
Test
I'll give you a little advice on the test.
- Presentation layer: Use the Android automated test tools instrumentation and espresso for integration and functional testing.
- Logical layer: Use JUnit and Mockito for unit testing.
- Data tier: Robolectric (because this layer has Android dependencies) and JUnit and Mockito for testing.
Conclusion
Architecture is designed to be realistic, not a framework. The architecture should be designed according to the actual situation. When designing the architecture, make sure that:
- Easy to maintain
- Easy to test
- High cohesion
- Low coupling
code example: see GitHub
Android Architecture ... What is the clear way?