Deep understanding of the impact of the communication mechanism between ANDROID components on object-oriented features detailed _android

Source: Internet
Author: User
Tags data structures sqlite sqlite database

Features of components
For Android, the four components of activity, service, ContentProvider and service, cannot have setters and getter, and cannot add interfaces to components. The reason is that the components are called to the system framework, the developer can only implement its specified callback interface, component creation and destruction are controlled by the system framework, developers can not force intervention, but also have no way to get the Component object. For example Activity,service,broadcastreceiver, you have no way to create a activity,service or broadcastreceiver, and then communicate with an interface like the other class that calls it, Use setters and getters to change properties, and so on. This also determines that communication between components can only be supported by a system-intent. Intent can only pass some common data types, such as basic data types and URIs. Intent only supports passing built-in types and some restriction types, which causes data passing between components to be basic types, so enum types cannot be used.
Polymorphism cannot be implemented
For example, you have a service that is used in the background to execute requests from the UI, some of which are for data requests, some for data analysis, and so on. Here you can use polymorphism, define a unified transaction class, and then for each specific transaction type, transaction the Unified Interface process () for actual processing, ideally, The service receives a transaction object and then calls its process (), there is no need to know the specific type, the UI creates a specific type object and then the service handles it. But this is not possible in Android because the intent communication mechanism is limited because it does not pass transaction objects directly. Therefore, the service must know the specific type. This is the case in native application MMS, where the transactionservice is the processing service in the transaction package, and the UI is sent to the service only to distinguish the ID (an integer) of the different transaction. The service looks at different IDs to create different transaction objects, and then invokes process () to process them.
Recommendation: Implement a service class of your own, using Handler,thread and looper to keep it running for a long time. There is no limit to the communication between components, you can use the service class like normal Java objects to pass a custom processing request to it:

Copy Code code as follows:

public class Transactionserver extends Handlerthread {
Public Transactionserver () {
Start ();
}
public void onlooperprepared () {
Mhandler = new Handler (Getlooper (), new Handler.callback () {
@Override
public void Handlemessage (msg) {
Transaction request = (Transaction) msg.obj;
Request.process ();
}
}
}

public void execute (Transaction request) {
if (Mhandler = = null) {
Return
}
Message msg = Message.obtain ();
Msg.obj = Request;
Mhandler.sendmessage (msg);
}
}


You can create an object of this server in the activity and then use it:
Copy Code code as follows:

Transactionserver Server = new Transactionserver ();
Transaction updaterequest = new Updatetransaction ();
Server.Execute (updaterequest);

In addition, with aidl and service communication, although you can get the service object reference, you can directly invoke the service method, but this also has limitations, for Aidl interface, all parameters and return type must be basic data
According to type, cannot have an object. The reason is understandable, because Aidl is also to pass IPC, even if the service and activity in the same process, so essentially it and intent communication mechanism is no different.
encapsulation is compromised.
The communication mechanism between components determines the encapsulation of Android, first of all to look at some examples:
Copy Code code as follows:

Intent i = new Intent (Intent.action_view);
I.setdataandtype (URI, "text/html");
StartActivity (i);

This is more common in Android.
The use of intent and intentfilter makes encapsulation much more damaging because you have to write strings, parameters, etc. directly into intent or intentfilter. For example:
Copy Code code as follows:

Intent i = new Intent ("Android.contacts.action.MULTIPLECONTACTSLISTS");
I.setextra ("Request_type", 3);
<intent-filter>
<action android:name= "Android.contacts.action.MULTIPLECONTACTSLISTS"/>
</intent-filter>

Of course, the best thing to do is:
Intent i = new Intent (contacts.action_get_contacts);
But in the androidmanifest of Intentfilter still want to write string constants (Literal Strings), so there is a problem, even if you write wrong, the compiler will not remind you, until you run to find the program does not work, you debug Ah, debugging, and finally found that the string was written incorrectly. Alternatively, the name of the activity is incorrectly written, and the compiler will not remind you, but you run the runtimeexception because you can't find the class.
Recommendation: define constants in all scopes as much as possible so that the interfaces between components are consistent, especially for string constants, and you must define constants in scopes that are visible to all two components, otherwise there will be maintenance trouble.
Example: Intent.putextra ("Request_type", 3); --> Intent.putextra (Targetactivity.request_type, targetactivity.no_background); otherwise, especially if the target component is not in the same package, or is far away, If the other party changes, the compile will not be wrong, but the program does not work properly, resulting in difficult to detect bugs.
Unable to pass custom data structures between components
As mentioned earlier, because you cannot get a reference to a component's object, you cannot set the data to it, of course, it can be static, but not elegant and difficult to maintain (for service it is possible to get a reference to a service object by Aidl and then call its methods to add data). And because intent can only carry basic data types, it's particularly troublesome for custom data structures to pass between components. Of course you can use the data structure to implement Parcleable interface, but it is also quite troublesome.
Recommendations:
1. Avoid using custom data structures as much as possible, especially in data structures other than setters and getters that do not have other behaviors
For structured data, define contentprovider for it, write data to the SQLite database, so that each row of data in a database table is equivalent to a data object, each column being its property. Because the Android component and the SQLite database are very viscous, each component can easily get data from the database, and then through the cursor tools to manipulate the data. Most importantly, it is very convenient to pass data between the components, the factor ContentProvider access is implemented through the URI, and the URI can be seamless with intent, the URI can be conveniently placed and removed from the intent, Each component can also directly access ContentProvider to read data with a URI, which enables seamless data transfer between components.
2. Do not pass data between components as far as possible
Do not use too much activity,service also can avoid, activity+ thread may solve most of the problems, of course, thread is not so useful, especially in Android.
3. Avoid passing custom data structures between components
As mentioned earlier, it is best to pass basic data and intent supported data types between components. For a custom data structure, either no data structures are defined or not passed between components, which can be cumbersome, although it may be possible to implement the Parcelable interface, but the efficiency and ease of operation will be greatly compromised.
about enumerations and sets of integers
A previous article <android Development notes: Use Enum (enum type) to replace the full set of applications >It has been said to try to use enumerations (enums) instead of integer sets (INTs). And many programming books (effective Java) also recommend enumerating instead of integer sets, which is the benefit of reducing the error rate, the Run-time check can be placed at compile time, because the range of integers is large, you can pass any number of integers Until the runtime detects or causes a problem, but the enumeration checks the type at compile time, and if it is not a legitimate enumeration, the compiler complains.
But we can see that the situation in Android is poor, and Android uses an integer set in large quantities, and the system defines a large number of integer sets, many of which are integers, although the correct approach is to pass the integer constants defined to these APIs, but if you pass a Integer.max _value or Integer.min_value, at least at compile time will not be a problem.
Since this is not a good programming specification, why does Android have to use an integer set in large numbers? The reason is the communication between components, the parameters to be passed between components, but the intent can only be put into the basic data type, that is, if you use enumerations, you will not be able to pass the intent to other components, because it is easy to convert an integer to an integer, but it is not so easy to turn
So if your constants don't need to be passed back and forth between components, it's best to define them as enumerations, otherwise you can only use an integer set.
about the general design principles of components
1. Do not use components to implement certain interfaces, such as click on the interface, and so on
Because the component is a very expensive object, the component's inheritance hierarchy is also very deep, with the component implementation interface, passed to the caller, is equivalent to a train to transport a small mouse, give someone a considerable object, but only one or two methods are needed by others. Especially for activity, Instead of implementing some common interfaces such as View.onclicklistener, the other one is that your onclick must use conditions to distinguish which UI element is clicked, which is difficult to maintain, and one reason is that the object of the activity is not very stable because some of the events in the system turn screen, language switching, etc. will kill the activity and recreate an instance, so it is possible to cause problems, although it seems that the activity is still there, but not the same instance, if something is related to a specific instance, it can cause problems, or the program does not work properly. or have runtimeexception. It is also possible to cause a memory leak because the interface object given to the consumer is an instance reference to the activity, and a memory leak occurs when a reference exceeds the lifecycle of the activity.
The recommended approach is to implement an interface with anonymous inner classes, and if other places require operations on this interface object, you can declare a member variable or an inner class, which is also convenient for the activity to control to ensure that everything survives within the lifetime of the event.
2. Use less service
Component service is not legendary to use, and it will allow your program to exit the page is still running in the background, accounting for system resources do not say, will be scolded (see these articles), because the service life cycle is controlled by the system, we can not intervene, Even if you know for certain that you are not using it at all. You can do most of the work with activities and threads, and you can do all the threads within the control of the activity so that they all live within the life cycle of activities. Another reason is that because threads belong to a custom class, or to a normal Java class, you can apply object-oriented because there is no restriction on component communication.
3. Using ContentProvider to do complex data structure of communication tools
ContentProvider and Sqlitedatabase Store the structured data, which is the equivalent of a data structure, and its reference is its URI, any component can obtain this data structure through a URI. It has the following advantages:
1. Can be easily transferred between components
Because the data is actually in the database, you only pass its address URI between the components, any component or any class holding the context can easily obtain it, whether in terms of practicality or efficiency, this is faster than using intent, or actually transferring data structure objects.
2. The ContentProvider component has its own processes and threads and does not have thread sync problems
External is through Contentresolver to access ContentProvider, so contentprovider to the outside world is the same, access the same way, naturally will not be wired to sync and so on.
3. ContentProvider can be encapsulated to make the data operation more convenient
Because Contentprovier provides a unified interface, you can take advantage of the characteristics of the data itself, and do some encapsulation when implementing these interfaces, such as adding default values, and so on.
4. ContentProvider can be used as a queue or stack
Because each row is a structured data, the data in each row is inserted sequentially, so it can be used as a queue, or as a stack.

You can refer to the sending process of the information in the native MMS, the information is written to the database from the user clicks, and then the URI is passed among the components, each component updates the status of the information, until the last send. There is also the default download in Downloadprovider,android, the application is submitted to a request via Downloadmanager, but the actual download is Downloadservice, And Downloadserver is in the Packages/provider/downloadprovider, is a completely independent process. Downloadmanager only writes a request to the Downloadprovider, which contains information such as URLs for downloading one thing. Downloadservice only listens for downloadprovider changes, and once a new data is inserted, create a thread to read the request and start the download. At the same time, the data is updated directly into the Downloadprovider, so that the UI can display information such as progress. This process involves two processes, at least three components: the user process that submits the request and the Downloadprovider process, Downloadmanager (is a public API), Downloadservice (separate process, Private package) and Downloadlist (the UI used to display the download progress inside the Downloadprovider package), there is no direct communication between these components, they are all around the contentprovider. At the same time, the ContentProvider is also used to download the requested queue, Downloadmanager can constantly add requests to it, Downloadservice will listen to its changes from which to take out the data and then do the download.
don't say Android development is simple.
While Android is easy to get started with, it's not easy to write good code, fragmentation, fragmentation, system architecture, and so on, which makes a lot of things harder. You can look at the main activity code in the primary application is more than 5000 lines, their interface is more complex, is the main core business logic, these activities control more things, so very bloated. The main reason here, of course, is not to have good design and refactoring. For example, the browser in ICS do a bit better, its browseractivity only hundreds of lines of code, but the previous code is more than 6,000 lines, now it separate the various business logic, activity is only responsible for receiving the frameworks layer of the callback, All business logic controls are handed over to controller, while controller is responsible for tab management, menu management, and so on. Specific menu and layout resolution related things to Phoneui to deal with. The process of downloading is handled by Downloadhandler and so on. All these things are put in the browseractivity, can imagine the original logic inside it will be how chaotic, maintenance will be how painful. Of course, now the design has yet to be improved, because the coupling between the classes is still very large, such as controller holding Phoneui objects, but Phoneui objects hold controller, and so on. Many times there will be calls to each other, which is quite difficult to maintain, but also undermines a considerable number of design principles.

In short, all procedures, if you want to write good, you need to submit additional energy, platform, although there are pros and cons but more importantly, the effort to invest in the code. But now sadly, Android platform profit is not ideal, coupled with fragmentation and impetuous psychology, so that many applications are made in one or two months, so the entire Android ecosystem, the quality of the application is not high, more serious is the reverse compilation and cloning, many people are the application to grasp down, Decompile and then changed is a new application, the more so do not pay attention to quality, the more users do not buy accounts, developers can not profit, the more difficult to invest in the application, so into a vicious circle.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.