Full interpretation of the four major components of Android

"How should I design my APP? What architecture pattern should I adopt? Do I need to use event bus?"

We often see Android platform developers asking questions about design patterns and architectures used in apps. But the answer is likely to surprise you, that is, we (we mean the Android Platform Team) do not have a clear view on this, and it can even be said that we have no view at all.

Should you use MVC or MVP or MVVM? I do not know. In fact, I only knew MVC when I was in school, and the other architectural patterns were written here after I did a temporary Google search.

This may be surprising, because Android gives people the feeling that it has a very strong view on how to write apps. This view is reflected in some high-level concepts such as its Java APIs and four major components. These things look like Form a typical application development framework, tell us developers, you should implement your functions in this way. But the reality is that this is not the case at all.

We can call Android core APIs (core APIs) the "system framework", and the main function of platform APIs is to define how the APP should interact with the operating system, and has nothing to do with the internal operating logic of the APP.

Personal understanding : You can simply regard core APIs as the operating system kernel, and platform APIs as the Android Framework we often say.

That is to say, for platform APIs, the functions and functions of platform APIs are often inconsistent from the perspective of developers and from the perspective of operating systems, which can easily confuse people in their use.

For example, let's consider how the operating system defines "how to run an APP". In a classic system, the most basic thing is to require the APP to include a main method, which defines how to run it:

int main(...){
//我的APP从这里开始运行
}

Personal understanding : The core idea of ​​this article is to explain that the so-called four major components just let your APP tell the operating system how to run it, and it has nothing to do with how to design your own APP. Traditional applications use a main method to tell the operating system: "Hey buddy, the main method is my entrance, please start running me from this method." Android gives you four choices, each component is for the operating system A kind of entrance to run your APP.

Well, the operating system is about to run your APP, so it calls your main method, and then your application starts to run, you can do whatever you want, until you think you have completed the task. Please note that the requirement for you to define the main method here is not for you to do anything or complete a function called main. The main function of the main method is only to provide an entry point for the APP to run.

But in the Android world, we decided that we don't want a clear main method as the entrance of the APP. Because we need to give the system more control over how the APP runs. In 我们希望构建一个这样的系统,在该系统中,用户永远不需要考虑开启和停止一个APP,而把这些事交给系统去管理particular, . Therefore, the system needs to know more about the internal operation of each APP so that it can start the APP in a defined way when needed, even if the APP is not running at the time.

Personal understanding : The internal operation of each APP that this system needs to understand is actually the content in the Manifest.xml file.

To achieve this, we decompose the main method of an APP into several forms that the system can interact with. This is several forms Activity, BroadcastReceiver, Serviceand ContentProviderAPIs, the majority of Android developers are familiar with them.

这些类好像在告诉你,你的APP内部应当怎样工作,但这是一种误解!事实上,这些类只是定义你的APP需要怎样与系统交互(以及系统怎样协调你的APP与其他APP进行交互)。这种与系统的交互一旦开始,系统就不再关心你的APP内部是怎样运行了。

In order to better illustrate this point, let us briefly look at what these APIs mean for the Android system.

Activity

This is the entry point for an APP to interact with users. From a system perspective, the key interaction actions provided by the system for Activity are:

  1. Keep track of what the user is currently caring about (that is, what is displayed on the screen) to ensure that the current process keeps running.

    Personal understanding : Here, the author actually means that when your application is started by the system from the Activity, between the start and stop states of the Activity, the system will ensure that the Activity always occupies the screen of the device and that your application Will never be killed by the system. This is a kind of promise (just a promise) given by the system to your APP when you start your own APP from Activity.

  2. Know the processes that have been used before. These processes contain the stopped activities that the user may return to, and therefore give these processes a higher priority.

  3. Help the application handle the situation where the process is killed, so that the user can return to the previous activities, and these activities can load their previous state

    Personal understanding : Obviously, this state of the system promised recovery capabilities, is to rely on Activitythe onSaveInstanceStateand onRestoreInstanceStatemethods, that is, you want to keep it you want to save in the process of being killed in the Save method Activity status, then you You can get these states in the Restore method to restore the Activity. When you do this, the rest is the system's business, the system will promise, if the process where your Activity is killed due to memory pressure, then when you return, the system will rebuild your application process, and Help you restore the state of the previous Activity.

  4. Provide a way of user flow between different applications. Of course, this depends on the system to coordinate. The most classic example is the realization of the sharing function.

For Activity, what the system does not care about is:

Once the system enters your APP UI from the Activity entrance, the system will no longer care about the organization of the internal logic of the Activity. You can put all application logic into this activity. For example, you can manually change its views, use fragments or other frameworks, or you can split your application logic into additional internal activities. You can also use the three at the same time (referring to changing views, using fragemnts, and splitting them into additional activities). The system does not care about these things, as long as you follow the agreement between the Activity and the system (start it in an appropriate state, save/restore its state correctly).

BroadcastReceiver

This is a mechanism that allows the system to pass events to the APP in addition to the normal user flow. Most importantly, because this is the entrance to another well-defined APP, the system can deliver broadcasts to the APP even if the APP is not currently running. So, for example, an APP can schedule an alarm in advance to notify the user of an upcoming event. By passing the alarm to a BroadcastReceiver of the APP, the APP does not need to run before the alarm occurs.

For BroadcastReceiver, what the system does not care about is:

在APP内部分发事件Is a BroadcastReceiver and receive event completely different things, whether you are using some eventbus framework, implement your own callback system, or any other method ...你都没有理由使用系统的广播机制,因为你并不是在App之间分发事件 .

In fact, there is a good reason not to use the system's broadcast mechanism, which will bring a lot of unnecessary burdens, and the use of the global broadcast mechanism to implement event distribution within the APP will cause many security problems.

Of course, we also provide a LocalBroadcastManager convenience class, which implements a pure intent distribution system, and its API is very similar to the system BroadcastReceiver API, you can use it if you like. 但再次强调,你没有理由在仅仅发生在APP中的事情上使用BroadcastReceiver机制.

Service

When the APP is required to run in the background for various reasons, Service is one such entry. There are two semantically distinct Services (one is Started Service, the other is Bound Service) to tell the system how to manage an APP.

Started Service is equivalent to your APP telling the system for some reason: "Big Brother, I have something to do, please let me run until I tell you that I'm done." (I am equivalent to APP, because at this time The Service represents the APP, and the system only talks to the APP) The "thing" here may be to synchronize data in the background or play music after the user leaves the APP.

At the same time, there are two kinds of Started Service, one is perceivable by users, and the other is not perceptible by users. These two different Started Services will allow the system to adopt different management methods for them.

  1. The service that plays music is directly perceivable by the user, so the Service will say to the system: "I want to be the foreground, and hang a notification in the notification bar so that the user can feel my presence." In this case, the system Knowing that you must use your best efforts to ensure the operation of this service process, because if this process goes down, the user will be unhappy.
  2. Another background service is not directly perceivable by users, so the system can handle the process of this service more flexibly. When the system urgently needs RAM to ensure the normal operation of the user's immediate things, the system may allow the process to be killed (then the Service can be started later when it is capable).

The Bound Service runs because other apps or systems use it. Usually, the Service will provide an API to other processes. In this case, the system knows that there is a dependency between the two processes. Therefore, if process A is bound to a Service in process B, the system will know that it must ensure the normal operation of process B and its services for process A. Furthermore, if process A is the process that the user is currently caring about, the system will know that process B is also the process that the user is caring about.

Due to the flexibility of Service (both good and bad), Service has become a very useful building block in various types of systems. Real-time wallpapers, notification listeners, and many other system core features are built as services, and when they need to run, the system binds them.

For Service, what the system does not care about is:

Android does not care about things in your APP that do not affect how it treats your process, so there is no reason to use Service in these situations. For example, if you want to download data for your UI in the background, you should not use Service to do this. When doing these things, it is really important not to tell the system to keep your process running. Because it is really unnecessary! ! Doing so also gives the system more freedom to manage your process in order to coordinate with what the user is doing ( 注:可以让系统在内存紧急的情况下,杀死你的进程,优先保证用户正在做的事情,这里忍不住吐槽一句:每个APP肯定都会觉得自己是最重要的哈,Google开发Android的人也是典型的理想主义!)

If you simply start a background thread to download data (or other methods that are not Service), you will get the result you want: if the user is in your UI, the system will ensure that your process is running. So the download will never be interrupted. When the user leaves your UI, your process will still be maintained (cached) so you can continue to download data, as long as the RAM is not in a hurry.

Similarly, in order to connect different parts of your APP, you have no reason to bind the Service in the same process. There is no obvious harm in doing so, because the system will see that the process has a dependency on itself, and it will ignore this dependency and still treat your APP as a normal process. But this is actually unnecessary for you and the system. As an alternative, you can use singletons or other in-process patterns to connect parts of your app together.

ContentProvider

Finally, ContentProvider is a dedicated method used to expose your APP data to other places. People usually think of them as an abstraction to the database, because there are many APIs and support libraries that use ContentProvider in this way. But from the perspective of system design, this is not the original intention of ContentProvider.

For the system, ContentProvider is actually an entry point for obtaining publicly named data items (data items) inside an APP, and each data item is identified by a URI scheme. In this way, the APP can decide how to map its own data items to a URI scheme, and how to expose this URI scheme to other APPs or systems, so that the APP or system can use this URI scheme to obtain its own internal data. This will allow the system to manage your APP in some very unique ways:

  1. Exposing the URI scheme does not require your APP to keep running, so even if your APP is not running, these URI schemes can be exposed to any apps and systems. Only when someone tells the system: "Please give me the data represented by this URI.", the system will let your APP run and ask you for the data items corresponding to the URI and return it to the requester.
  2. These URIs also provide an important fine-grained security model. For example, your app can put a URI representing a picture in your app on the clipboard, but keep its ContendProvider locked, so no one can get it freely. When another APP obtains this URI from the clipboard and requests the system to obtain the corresponding picture, the system can give it a temporary "URI permission" so that it can only obtain the picture corresponding to the URI, your APP The rest of the content is safe.

For ContentProvider, what the system does not care about is:

Behind a ContentProvider, the system doesn't care how your APP manages your data; if you don't need the structured data in the SQLite database, you don't need to use SQLite. For example, the FileProvider helper class allows the original files in your APP to be easily obtained through a ContentProvider.

Similarly, if you don't plan to disclose the data in your app for others to use, you don't need to implement ContentProvider. This is the case, because there are many convenient methods around ContentProvider. These methods allow you to easily store data in the SQLite database and fill UI elements such as ListView with these data. But if these methods make you feel that it is difficult to realize your own ideas, you don't need to use them. Please feel free to choose a data model that is suitable for your APP.

Guess you like

Origin blog.csdn.net/zhireshini233/article/details/114992122