Android development Note: how to replace Integer Set with Enum (Enumeration type)

Source: Internet
Author: User
Tags constant definition

Many Android APIs use integer sets as parameters. Let's take a look at the instance.
LinearLayout is a well-known basic UI element. It has a direction attribute and can be set using the following methods:
Copy codeThe Code is as follows: LinearLayout. setOrientation (int );

This is usually used in the following scenarios:Copy codeThe Code is as follows: LinearLayout. setOrientation (LinearLayout. HORIZONTAL );
LinearLayout. setOrientation (LinearLayout. VERTICAL );

But it can also be used as follows:Copy codeThe Code is as follows: LinearLayout. setOrientation (0); // LinearLayout. HORIZONTAL = 0
LinearLayout. setOrientation (1); // LinearLayout. VERTICAL = 0x01

You can even do this:Copy codeThe Code is as follows: LinearLayout. setOrientation (Integer. MAX_VALUE );
LinearLayout. setOrientation (Integer. MIN_VALUE );
LinearLayout. setOrientation (2012 );

Because the parameter received by the setOrientation method is an integer, you can pass any valid integer-at least this will not cause any problems during compilation. It can only cause problems at runtime, but as you know, developers only focus on whether the program can be compiled successfully. As for runtime, it is a matter of concern to users, because developers do not necessarily use the programs they have developed.

In addition to this example, you can see this API everywhere in the Android API, such as setting the View visibility and setting the Wifi status. All of them define the Integer Set, and then use the integer as the parameter, and hope that the developer can pass the constant defined in the integer set as the parameter. But as you know, not everyone is so disciplined. If everyone can abide by the rules, the world will be truly harmonious.
Because developers can only focus on compilation, if you can apply this rule during compilation, it will greatly reduce the possibility of errors. If you are interested, you can try it and pass some "common" values, such as 2012 and Integer, to the methods that receive Integer parameters. MAX_VALUE, Integer. MIN_VALUE.
In addition, if the developer passes an integer consistent with the constant definition, although compilation and Running won't be wrong, the Code's readability will be greatly reduced, for example:Copy codeThe Code is as follows: LinearLayout. setOrientation (0 );
LinearLayout. setOrientation (1 );

This is completely correct, but the reader and maintainer of the Code usually suffer.
Of course, Android still has protective measures. If an invalid parameter is passed to the API, it will not affect others, but the setting cannot take effect, but the API will use the default value, because for each built-in parameter, all have corresponding default values. For example, the orientation of LinearLayout. The default value is LinearLayout. HORIZONTAL. Therefore, if an invalid value is input to setOrientation (), LinearLayout will be horizontally arranged without any other impact. There is an experiment on orientation of Linearlayout later.
In addition, if you set these attributes in the Layout XML file, there will be no problems, such:Copy codeThe Code is as follows: <LinearLayout
Android: orientation = "vertical"
Android: gravity = "center">

Because the XML layout will be processed during compilation, and if there are invalid values, there will be compilation errors. I think that is one reason why Android especially encourages developers to use XML to make all la S. Example: Three linear la s with no points set. By default, they are placed horizontally. Several outrageous values are set in the Code and they are still horizontal. That is to say, setting the outrageous values will not go wrong, but it does not work either: the running result is as follows:


The Code is as follows:

Copy codeThe Code is as follows: <? Xml version = "1.0" encoding = "UTF-8"?>
<LinearLayout xmlns: android = "http://schemas.android.com/apk/res/android"
Android: orientation = "vertical"
Android: layout_width = "fill_parent"
Android: layout_height = "fill_parent"
Android: gravity = "center"
>
<LinearLayout
Android: id = "@ + id/linearlayout_test_1"
Android: layout_width = "fill_parent"
Android: layout_height = "wrap_content">

<TextView
Android: layout_width = "wrap_content"
Android: layout_height = "wrap_content"
Android: textColor = "# ff00ff00"
Android: background = "# aa331155"
Android: layout_weight = "1"
Android: textSize = "18sp"
Android: text = "Microsoft"
/>
<TextView
Android: layout_width = "wrap_content"
Android: layout_height = "wrap_content"
Android: textColor = "# ffff0000"
Android: background = "# aa117711"
Android: layout_weight = "1"
Android: textSize = "18sp"
Android: text = "Apple"
/>
<TextView
Android: layout_width = "wrap_content"
Android: layout_height = "wrap_content"
Android: textColor = "# ff0000ff"
Android: background = "# aa774411"
Android: layout_weight = "1"
Android: textSize = "18sp"
Android: text = "Google"
/>
</LinearLayout>
<LinearLayout
Android: id = "@ + id/linearlayout_test_2"
Android: layout_width = "fill_parent"
Android: layout_height = "wrap_content">

<TextView
Android: layout_width = "wrap_content"
Android: layout_height = "wrap_content"
Android: textColor = "# ff00ff00"
Android: background = "# aa331155"
Android: layout_weight = "1"
Android: textSize = "18sp"
Android: text = "Microsoft"
/>
<TextView
Android: layout_width = "wrap_content"
Android: layout_height = "wrap_content"
Android: textColor = "# ffff0000"
Android: background = "# aa117711"
Android: layout_weight = "1"
Android: textSize = "18sp"
Android: text = "Apple"
/>
<TextView
Android: layout_width = "wrap_content"
Android: layout_height = "wrap_content"
Android: textColor = "# ff0000ff"
Android: background = "# aa774411"
Android: layout_weight = "1"
Android: textSize = "18sp"
Android: text = "Google"
/>
</LinearLayout>
<LinearLayout
Android: id = "@ + id/linearlayout_test_3"
Android: layout_width = "fill_parent"
Android: layout_height = "wrap_content">

<TextView
Android: layout_width = "wrap_content"
Android: layout_height = "wrap_content"
Android: textColor = "# ff00ff00"
Android: background = "# aa331155"
Android: layout_weight = "1"
Android: textSize = "18sp"
Android: text = "Microsoft"
/>
<TextView
Android: layout_width = "wrap_content"
Android: layout_height = "wrap_content"
Android: textColor = "# ffff0000"
Android: background = "# aa117711"
Android: layout_weight = "1"
Android: textSize = "18sp"
Android: text = "Apple"
/>
<TextView
Android: layout_width = "wrap_content"
Android: layout_height = "wrap_content"
Android: textColor = "# ff0000ff"
Android: background = "# aa774411"
Android: layout_weight = "1"
Android: textSize = "18sp"
Android: text = "Google"
/>
</LinearLayout>
</LinearLayout>

And:Copy codeThe Code is as follows: package com. android. explorer;
Import android. app. Activity;
Import android. OS. Bundle;
Import android. widget. LinearLayout;
Public class LinearLayoutTest extends Activity {
@ Override
Public void onCreate (Bundle savedInstanceState ){
Super. onCreate (savedInstanceState );
SetContentView (R. layout. linearlayout_test );
LinearLayout one = (LinearLayout) findViewById (R. id. linearlayout_test_1 );
One. setOrientation (2012 );
LinearLayout two = (LinearLayout) findViewById (R. id. linearlayout_test_2 );
Two. setOrientation (Integer. MAX_VALUE );
LinearLayout three = (LinearLayout) findViewById (R. id. linearlayout_test_3 );
Three. setOrientation (Integer. MIN_VALUE );
}
}

Use Enum instead of Integer Set
In fact, it is very simple to use Enum (enumeration) to easily solve this problem. It is no longer cumbersome to use than to define an integer set and is also readable. Another advantage is that it is better encapsulated, and most importantly, it will be checked during compilation. Because Java is a Strong Type, that is, during compilation, the compiler checks all prototype and parameter types. If the Type is incorrect and there is no forced transformation, A compilation error is reported, except for the automatic transformation supported by the compiler. For example, if an int is required, and the input parameter is long, although it is similar, there is no overflow, but there will still be compilation errors.
Therefore, if LinearLayout uses Enum, it is defined as follows:Copy codeThe Code is as follows: public class LinearLayout extends ViewGroup {
Private Orientation mOrientation;

Public enum Orientation {
HORIZONTAL, VERTICAL
};

Public void setOrientation (Orientation dir ){
MOrientation = dir;
}
}

Then use the following code:Copy codeThe Code is as follows: import android. widget. LinearLayout;
LinearLayout. setOrientation (Orientation. HORIZONTAL );
LinearLayout. setOrientation (Orientation. VERTICAL );

Then, the developer will not use the error, because first, it will see that the parameter required by setOrientation is an enumeration type of Orientation, it will naturally transfer the type defined in Orientation; in addition, if other values, such as 0 or 1, are passed, the compiler will not agree.

Sadly, almost all APIs in Android are defined as integer sets. Therefore, you must always remind yourself and the people in the group to pass the constants in the defined Integer Set.
What we can do is not to pass the constants defined in the Integer Set, but to the APIS defined in the Integer Set Method. More importantly, when you define your own interface, try to use Enum instead of an integer set.
Note that for some weak types of languages, that is to say, classes are not checked in detail during compilation, such as C ++ and C, even if Enum is used, it is not necessarily safe, because for C ++ and C, the constants in Enum are exactly the same as Integer constants, and the compiler cannot tell. Therefore, developers can only hope for such languages.
Postscript:
This article reminds me of some other problems related to Parameter definition. For example, Boolean parameters are not a good design, because it is difficult for users to pass True or False, especially when the method name does not reflect the role of the Boolean parameter and the document is not clear enough. If there is only one parameter, you can know it based on the method name and common sense, for example:Copy codeThe Code is as follows: Button. setEnabled (true); // enable the button
Button. setEnabled (false); // disable the button

However, in some cases, when the method name does not reflect the role of the Boolean parameter, or when there is more than one parameter, and the main purpose of the method does not reflect the role of the Boolean parameter, it is not clear, for example:Copy codeThe Code is as follows: // com/android/mms/data/ContactList. java
Public String [] getNumbers (boolean );

Can you guess that this boolean variable determines whether to perform special processing on contacts for MMs? When using this API, do you soon know whether to pass True or False? When reading these statements:Copy codeThe Code is as follows: String [] mms = getNumbers (true );
String [] sms = getNumbers (false );

Do you know the meanings and functions of True and False? At least I can't guess if I don't trace the implementation of this code.
But the reality is that the API usually needs to be determined by the caller or not. A feasible approach is to encapsulate and hide the data using methods, such:Copy codeThe Code is as follows: Button. setEnabled (true); // enable the button
Button. setEnabled (false); // disable the button

You can change it:Copy codeThe Code is as follows: Button. enable ();
Button. disable ();

This is a simple case. For a slightly complex case, for example, in the next example, you can add another interface, instead of using the overload method. However, the internal implementation may still need to be overloaded, however, this reduces the problem, which is hidden to users at least:Copy codeThe Code is as follows: // com/android/mms/data/ContactList. java
Public String [] getNumbersForSms ();
Public String [] getNumbersForMms ();

In this way, it is a good encapsulation. The internal implementation may still require a private method like this:Copy codeThe Code is as follows: // com/android/mms/data/ContactList. java
Public String [] getNumbersForSms (){
Return getNumbers (false );
}
Public String [] getNumbersForMms (){
Return getNumbers (true );
}
Private String [] getNumbers (boolean ){
// Implementation
}

But at least the problem is reduced. You can also add notes to describe the problem. You don't have to guess the usage and meaning of the method.

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.