实战技巧:用Enum(枚举类型)取代整数集
在Android的API中可以发现有很多用整数集来作为参数的地方,先来看一下实例。 LinearLayout是大家所熟知的一个UI基本元素,它里面有一个方向的属性,可以通过以下方法来设置: LinearLayout.setOrientation(int); 使用的时候,通常都是这样: LinearLayout.s
在Android的API中可以发现有很多用整数集来作为参数的地方,先来看一下实例。LinearLayout是大家所熟知的一个UI基本元素,它里面有一个方向的属性,可以通过以下方法来设置:
LinearLayout.setOrientation(int);
LinearLayout.setOrientation(LinearLayout.HORIZONTAL); LinearLayout.setOrientation(LinearLayout.VERTICAL);
LinearLayout.setOrientation(0); // LinearLayout.HORIZONTAL = 0 LinearLayout.setOrientation(1); // LinearLayout.VERTICAL = 0x01
LinearLayout.setOrientation(Integer.MAX_VALUE); LinearLayout.setOrientation(Integer.MIN_VALUE); LinearLayout.setOrientation(2012);
除了这个例子,在Android的API中到处可以看到这种API,比如设置View的可见性,设置Wifi状态等等。都是定义了整数集,然后用整数来做为参数,并寄希望开发者能传递整数集中定义的常量来作为参数。但如你所知,并不是每个人都那么的守规矩,如果每个人都能遵守规则,这个世界就真的和谐了,蛋扯远了。
因为开发者通常只能关注编译,所以如果能把这个规则应用在编译时,那么就会大大减少出错的可能。有兴趣的朋友可以去试试看,给这些接收整数参数的方法传一些“平常”的数值,比如2012,Integer.MAX_VALUE,Integer.MIN_VALUE等等,看会出现什么状况。
另外,如果开发者传递与常量定义一致的整数值,虽然编译运行都不会有错,但代码的可读性会大大的降低,比如:
LinearLayout.setOrientation(0); LinearLayout.setOrientation(1);
当然,Android自身还是有保护措施的,如果对API传递不合法参数,不会造成其他影响,只是设置不能生效,但API会使用默认值,因为对于每个内置参数,都有相应的默认值。如LinearLayout的orientation,默认值就是LinearLayout.HORIZONTAL,所以如果对setOrientation()传入非法值,LinearLayout会保持水平排列,无其他影响。后面有个对Linearlayout的orientation做的试验。
另外,如果在Layout XML文件中设置这些属性就不会有些问题,如:
<linearlayout android:orientation="vertical" android:gravity="center"></linearlayout>
因为XML布局会在编译时被处理,如果有非法的值,会有编译错误的。我想这也就是Android特别鼓励开发者用XML来制作所有的布局的一个原因吧。
实例,三个没有设置指向的线性布局,默认是水平放置,在代码中设置了几个离谱的值,发现它们还是水平的,也就是说设置离谱的值不会出错,但也不起作用:
运行结果如下:
代码如下:
<?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> <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> <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"></textview> </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> <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> <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"></textview> </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> <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> <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"></textview> </linearlayout> </linearlayout>
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); } }
用Enum代替整数集
其实很简单,用Enum(枚举)就可以很方便的解决这个问题,使用起来也不比定义整数集繁琐,同样的可读。另外的优点就是,它的封装更好,最重要的是它会在编译时被检查。因为Java是一种Strong Type,也就是说在编译时,编译器会对所有原型类型和参数类型进行检查,如果类型不对,并且没有强制转型的,就会报出编译错误,当然编译器所支持的自动转型除外。比如一个需要int,而传的参数是long,虽然都差不多,没有溢出等,但还是会有编译错误。所以,如果LinearLayout使用Enum,就像这样定义:
public class LinearLayout extends ViewGroup { private Orientation mOrientation; public enum Orientation { HORIZONTAL, VERTICAL }; public void setOrientation(Orientation dir) { mOrientation = dir; } }
import android.widget.LinearLayout; LinearLayout.setOrientation(Orientation.HORIZONTAL); LinearLayout.setOrientation(Orientation.VERTICAL);
可悲的是Android中几乎所有的API都是以整数集的方式来定义的,所以就要时刻提醒自己和组里的人,一定要传所定义的整数集中的常量。
那么我们能做的,除了要传整数集中定义的常量,对于那些以整数集方式定义的API,以外。更重要的是当自己定义接口的时候,尽量用Enum而不要使用整数集。
还有一点需要注意的是,对于某些弱类型语言,也就是说在编译时不会对类型做特别细致的检查,比如C++,C等,那么即使使用了Enum,也不一定安全,因为对于C++和C来讲Enum中的常量与整数常量完全一样,连编译器都分不清。所以,对于这类语言,只能寄希望于开发者了。
后记:
写完这篇,让我想起了另外一些与参数定义相关的问题,比如布尔型参数也不是一个很好的设计,因为使用者很难到底应该传True还是传False,特别是当方法名字不能体现Boolean参数作用时和文档不够清楚的时候。如果只有一个参数还好,根据方法名字和常识都能知道,比如:Button.setEnabled(true); // enable the button Button.setEnabled(false); // disable the button
// com/android/mms/data/ContactList.java public String[] getNumbers(boolean);
String[] mms = getNumbers(true); String[] sms = getNumbers(false);
但现实的问题是,API通常又需要从调用者那里得到做还是不做的决定。一个可行的途径是用方法来封装和隐藏,比如:
Button.setEnabled(true); // enable the button Button.setEnabled(false); // disable the button
Button.enable(); Button.disable();
// com/android/mms/data/ContactList.java public String[] getNumbersForSms(); public String[] getNumbersForMms();
// com/android/mms/data/ContactList.java public String[] getNumbersForSms() { return getNumbers(false); } public String[] getNumbersForMms() { return getNumbers(true); } private String[] getNumbers(boolean) { // implementation }
对于使用Boolean作为参数的弊端,可以参考陈皓的这篇博客,讲的很透彻。

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제









최근 아이스 유니버스는 삼성의 차기 플래그십 스마트폰으로 널리 알려진 갤럭시 S25 울트라에 대한 세부 정보를 꾸준히 공개해 왔습니다. 무엇보다도 유출자는 삼성이 카메라 업그레이드를 하나만 가져올 계획이라고 주장했습니다.

OnLeaks는 이제 Android Headlines와 제휴하여 X(이전 Twitter) 팔로어로부터 4,000달러 이상의 수익을 창출하려는 시도가 실패한 지 며칠 후 Galaxy S25 Ultra에 대한 첫 번째 모습을 제공합니다. 맥락에 따라 h 아래에 포함된 렌더링 이미지

TCL은 두 가지 새로운 스마트폰을 발표하는 것과 함께 NXTPAPER 14라는 새로운 Android 태블릿도 발표했는데, TCL의 거대한 화면 크기는 판매 포인트 중 하나입니다. NXTPAPER 14는 TCL의 시그니처 브랜드인 무광택 LCD 패널 버전 3.0을 갖추고 있습니다.

최근 아이스 유니버스는 삼성의 차기 플래그십 스마트폰으로 널리 알려진 갤럭시 S25 울트라에 대한 세부 정보를 꾸준히 공개해 왔습니다. 무엇보다도 유출자는 삼성이 카메라 업그레이드를 하나만 가져올 계획이라고 주장했습니다.

Vivo Y300 Pro는 방금 완전히 공개되었으며 대용량 배터리를 갖춘 가장 얇은 중급 Android 휴대폰 중 하나입니다. 정확히 말하면 스마트폰의 두께는 7.69mm에 불과하지만 배터리 용량은 6,500mAh입니다. 최근 출시된 것과 동일한 용량이다.

삼성전자는 팬에디션(FE) 스마트폰 시리즈를 언제 업데이트할지 아직 힌트를 주지 않았다. 현재 상태로 Galaxy S23 FE는 2023년 10월 초에 출시된 회사의 최신 버전으로 남아 있습니다.

Redmi Note 14 Pro Plus는 이제 작년 Redmi Note 13 Pro Plus(Amazon에서 현재 $375)의 직접적인 후속 제품으로 공식화되었습니다. 예상대로 Redmi Note 14 Pro Plus는 Redmi Note 14 및 Redmi Note 14 Pro와 함께 Redmi Note 14 시리즈를 주도합니다. 리

모토로라는 올해 셀 수 없이 많은 기기를 출시했지만 그 중 폴더블 기기는 2개뿐이었습니다. 맥락에 따라 전 세계 대부분이 Razr 50 및 Razr 50 Ultra로 쌍을 받았지만 Motorola는 북미에서 Razr 2024 및 Razr 2로 제공합니다.
