Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to understand Android Architecture

2025-01-21 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article introduces the relevant knowledge of "how to understand Android architecture". Many people will encounter such a dilemma in the operation of actual cases, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

1. What is the significance of modularization? 1.1 basic concepts and underlying ideas

All modularization is designed to meet the single design principle (literally understood), a function or a class or a module, the more single the responsibility, the stronger the reusability, at the same time, it can indirectly reduce the coupling.

In the context of software engineering, changes are likely to go wrong, do not say "I pay attention to a point will not go wrong", because people are not machines. What we can do is to make the module as simple as possible, and the more single the responsibility, the less likely it is to affect the outer module, and the lower the probability of error.

So the core idea of modularization is: single design principle.

1.2 what features are we going to do modularization based on?

When doing modular processing, try to carry out functional features and business features based on two features.

Functional characteristics

Network, picture loading and so on can be called functional features. For example, the network: we can write the integration and encapsulation of the network framework into the same module (module, package, etc.), which can enhance readability (the same directory is clear at a glance), reduce the probability of misoperation, facilitate maintenance and make it more secure. At the same time, modules can be hosted to remote libraries such as maven, which can be used by multiple projects to further improve reusability.

Service characteristics

The literal meaning of business characteristics can be understood, that is, the business we often write needs to be divided into modules according to the characteristics of the business.

Why do business features take precedence over functional features?

An example is shown in the following figure:

I believe many people have seen or are using this subcontracting method. Is it reasonable to put all Adapter, Presenter, Activity, and so on in the corresponding package at the business layer? First of all, the answer is not reasonable. first of all, it is already in the business layer, and everything we do is actually serving the business layer, so the business should have the highest priority. We should give priority to putting the corresponding classes into the same package according to the business characteristics.

The core of the functional module is the function, which should be divided into modules by function. The core of the business module is the business, which should be divided first by the business, followed by the function.

1.3 how does Android do layering?

Front-end development is actually to do data handling, and then display it in the view. Data and view are two different concepts, in order to improve reusability and maintainability, we should layer them according to a single design principle, so the core point of MVC, MVP or MVVM is to layer data and view.

Stumbling block:

Generally speaking, the data structure we get through network requests is defined by the backend, which means that the view layer has to use the fields defined by the backend directly. Once the backend makes business adjustment, it will force our frontend to make corresponding changes from the data layer-> view layer, as shown in the pseudo code below:

/ / original logical data layer Model {title} UI layer View {textView = model.title} / / backend adjusted data layer Model {title prefix} UI layer View {textView = model.prefix + model.title}

At first, our textView displays the title in model, but after the backend adjustment, we need to add a prefix field to the model, and the textView display also needs to do a string concatenation. The view layer has been passively modified due to changes in the data layer. Now that we have done layering, what we want must be that the view and data do not interfere with each other, how to solve it? Look down.

1.4 Data Mapper may be the antidote

Data Mapper is a concept commonly used in the backend. In general, they do not directly use the fields in the database, but add a Data Mapper (data mapping) to convert the database table to Java Bean on demand. The benefit of this is also obvious. No matter how messy the table structure is, it will not affect the business layer code.

For the front end, I think we can properly introduce Data Mapper to transform the back-end data into a local model, which only corresponds to the design drawing, completely isolating the back-end business from the view. This solves the problems faced by 1.3 in the following ways:

Data layer Model {title prefix} local model (one-to-one correspondence with the design drawing) LocalModel {/ / convert the back-end model to the local model title = model.prefix + model.title} UI layer View {textView = localModel.title}

LocalModel is equivalent to an intermediate layer, isolating the data layer from the view layer through the adapter mode.

The front end can be developed without the backend after the introduction of Data Mapper. As long as the requirements are clear, you can do the development of the view layer. There is no need to worry about the structure and fields returned by the back end. And this practice is done once and for all. For example, if some fields need to be adjusted at the back end, we can go straight to the data layer without thinking. 100% of the adjustments involved will not affect the view layer.

Note:

At present, in order to separate the front and back end more thoroughly, some companies have the structure of Java Bean (equivalent to LocalModel) provided by front-end developers. The benefit is also obvious. More businesses are converged to the back end, which greatly improves the flexibility of the business. After all, the cost of sending a version of App is relatively high. Faced with this situation, there is no need to write Data Mapper. Therefore, any architectural design should be combined with the actual situation, suitable for their own is the best.

1.5 Business logic with nowhere to put

Business logic is actually a very general concept, and even any line of code can be called business logic. How should we understand such a broad concept? Let me first roughly divide it into two aspects:

Interface interaction logic: the interaction logic of the view layer, such as gesture control, suction suspension and so on, is implemented according to the business needs, so strictly speaking, this part also belongs to the business logic. But this part of the business logic is generally implemented in the view layer.

Data logic: this part is often referred to as business logic, which belongs to strong business logic, such as getting different data and displaying different interfaces according to different user types, and a series of operations of Data Mapper are just to cover the backend and help them complete the remaining logic. In order to make it easier for you to understand, I collectively refer to data logic as business logic.

As we mentioned earlier, Android development should have data layer and view layer, so which layer is more appropriate for business logic? For example, in MVVM mode, everyone says that business logic is handled by ViewModel, which is not a big problem, but if an interface is complex enough, the corresponding ViewModel code may have hundreds of lines, which will look bloated and poor readability. Most importantly, it is difficult for these businesses to write unit test cases.

I suggest writing a separate use case processing for business logic.

The use case is usually placed between the ViewModel/Presenter and the data layer, and the business logic and Data Mapper should be placed in the use case, with each behavior corresponding to a use case. This solves the problem of bloated ViewModel/Presenter and makes it easier to write test cases.

Note:

Good design is a specific scenario to solve specific problems, overdesign not only can not solve any problems, but will increase the cost of development. From my current experience, at least half of the scenarios of Android development are simple: request-> get data-> add a Data Mapper at most in the render view, and the process is very simple and may not be changed too much later. In this case, it is not necessary to write a use case,Data Mapper and throw it into the data layer.

two。 Reasonable layering is the groundwork for data-driven UI.

Let's start with the conclusion: the essence of data-driven UI is control inversion.

2.1 what is an inversion of control?

Control is the control of the program flow, which is generally undertaken by our developers, and this process is control. However, developers are human, so errors are inevitable. At this time, a mature framework can reverse the role. Programmers only need to add their own business code to the extension points reserved by the framework. The framework can be used to drive the execution of the entire program process. This process is reversed.

The concept of control inversion is similar to dependency inversion in design principles, except that one dependency abstraction is missing.

For example:

Existing requirements for a HTTP request, if you want to maintain your own HTTT links, manage your own TCP Socket, and handle your own HTTP cache. That is, the entire HTTP protocol is encapsulated by itself, not to mention whether the project can be realized by individuals, even if the implementation is full of loopholes, we can change our way of thinking at this time: to achieve through OkHttp, OkHttp is a mature framework that basically does not make mistakes. Individuals encapsulate the HTTP protocol to use the OkHttp framework, this process has a reversal in the role of controlling HTTP, the individual-> mature framework OkHttp is the inversion of control, and the benefits are obvious, and the probability of framework errors is much lower than that of individuals.

2.2 what is data-driven UI?

Generally speaking, when the data changes, the corresponding UI will also change, on the contrary, when you need to change the UI, you only need to change the corresponding data. Nowadays, the popular UI frameworks such as Flutter, Compose and Vue are all based on functional programming to implement data-driven UI. Their common purpose is to solve the problem of data and UI consistency.

In the current Android, you can use DataBinding to achieve the same effect. Take Jetpack MVVM as an example: ViewModel can achieve data-driven UI by temporarily storing data from Repository to the corresponding ObservableFiled of ViewModel, but only if the data obtained from Repository can be used directly. If you do secondary data processing in Activity or Adapter and then notify UI, it has violated the core idea of data-driven UI. Therefore, in order to achieve data-driven UI, there must be reasonable layering (the data obtained by the UI layer does not need to be processed and can be used directly). Data Mapper just solves this problem, and it can also avoid the current situation of writing a large number of BindAdapter.

DataBinding is not functional programming, it just generates intermediate code through AbstractProcessor to map data to XML

2.3 Why is the underlying idea of data-driven UI control inversion?

At present, there are only two frameworks for Android ecology to implement data binding UI: DataBinding and Compose (not discussed for the time being).

It usually takes two steps to render a piece of data before introducing DataBinding, as follows:

Var title = "iOS" fun setTitle () {/ / first step change data source title = "Android" / / second change UI textView = title}

It takes two steps to change the data source and change the UI. If one of the data sources and UI forgets to modify, BUG will appear. Never say, "I will never forget to modify both". When faced with complex logic and a dozen or even dozens of data sources, it is difficult to ensure that they will not make mistakes. This problem can be solved through DataBinding. As long as you change the corresponding ObservableFiledUI, it will be modified synchronously, and the UI status will be reversed from the individual to the DataBinding. DataBinding will not be responsible for personal negligence.

So the underlying idea of data-driven UI is control inversion.

2.4 Why was Diff introduced?

Before introducing diff:

If RecyclerView wants to delete, add and update dynamically, it needs to update data and UI manually respectively, so inserting a way in the middle and updating data and UI respectively has violated the aforementioned data-driven UI. What we want is that no matter delete, add or update, there is only one entry, as long as we change the data source, we will drive UI to do updates. To meet this principle, we can only refresh the RecyclerView after changing the data source. But this can cause performance problems, and complex interfaces can feel obviously stuttered.

After the introduction of diff:

Through the differential comparison of oldItem and newItem, the Diff algorithm automatically updates the changed item and supports deleted and added animation effects, which solves the performance problem of data-driven UI in RecyclerView.

3 Why do I recommend functional programming 3.1 what is functional programming?

One entrance, one exit.

Do not perform operations independent of the operation itself within the function chain

Do not use external variables within the function chain (in fact, this one is difficult to follow and can be broken through properly)

The popular point is that given an initial value, a target value will be obtained after the operation of the function chain, and there is no permission to intervene externally in the process of operation, and at the same time, it does not do any operation that has nothing to do with itself, which fundamentally solves the generation of unexpected errors.

For example:

/ / Kotlin code listOf (10,20). Map {it + 1}. ForEach {Log.i ("list", "$it")}

The above chain programming is standard functional programming, and there is no chance for developers to intervene between input and output (i.e. Log.i (..) Previously, developers do not have permission to deal with list), so the whole process is 100% secure. RxJava, Flow and chained high-order functions are all standard functional programming, which solve data security problems at the normative level. So I suggest that when dealing with data in Kotlin, try to use chained higher-order functions (RxJava, Kotlin Flow, too).

3.2 Android view development can learn from functional programming.

Most Android view developers follow the following process: request-- > process data-- > render UI. This process can learn from functional programming, using requests as entrances and rendering as exits. In this process, try not to do anything that has nothing to do with the current behavior (this also requires that the functions in ViewModel,Repository conform to a single principle). This is a bit general. Here is a counterexample:

View {/ / Refresh fun refresh () {ViewModel.load (true)} / / load more fun loadMore () {ViewModel.load (false)}} ViewModel {/ / load data load (isRefresh) {if (isRefresh) {/ / Brush New} else {/ / load more}

The View layer has two behaviors of refreshing and loading more. Load (isRefresh) has one entry and two exits. The problem is obvious, modify refresh or load more will have an impact on each other, in violation of the opening and closing principle (close to modification: behavior is not allowed to modify the source code), resulting in unexpected problems. We can improve it by using the idea of functional programming for reference, and split the load function of ViewModel into refresh and loadMore, so as to refresh and load more two behaviors, two entrances and two exits without interference with each other, and form two independent business chains through the convergence of functions.

Functional programming can constrain us to write standard code, in the face of scenarios where functional programming can not be used, we can try to self-restrict to the direction of functional programming, and roughly the same effect can be achieved.

This is the end of "how to understand Android Architecture". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report