开源中国源码学习(八)——枚举类

简介

感觉这主页面这块还是比较复杂的,这段时间在学习这部分的源码,一遍遍的读源码,收获比较大的一部分是主页面四个Tab页面的展现形式。
这块儿借助了枚举类来完成相应的操作,是以前没有涉及过的,感觉很新鲜。

TabHost的五个Tab初始化

总体来说就是通过枚举类来列出5个Tab对应的内容页。在源码中初始化五个Tab页的代码如下所示:

 //初始化底部的五个Tab页
 private void initTabs() {
            //调用枚举类MainTab的values方法,获得MainTab枚举类数组
        MainTab[] tabs = MainTab.values();

        final int size = tabs.length;
        for (int i = 0; i < size; i++) {
                 //根据index获得具体对应的MainTab
            MainTab mainTab = tabs[i];
            //初始化每个Tab对应的图标、文字
            TabSpec tab = mTabHost.newTabSpec(getString(mainTab.getResName()));
            View indicator = LayoutInflater.from(getApplicationContext())
                    .inflate(R.layout.tab_indicator, null);
            TextView title = (TextView) indicator.findViewById(R.id.tab_title);
            Drawable drawable = this.getResources().getDrawable(
                    mainTab.getResIcon());

            title.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null,
                    null);
            if (i == 2) {
                indicator.setVisibility(View.INVISIBLE);
                mTabHost.setNoTabChangedTag(getString(mainTab.getResName()));
            }
            title.setText(getString(mainTab.getResName()));
            tab.setIndicator(indicator);
            tab.setContent(new TabContentFactory() {

                @Override
                public View createTabContent(String tag) {
                    return new View(MainActivity.this);
                }
            });
            //为TabHost添加对应的页面内容
            mTabHost.addTab(tab, mainTab.getClz(), null);
                 //如果对应的是我的界面则添加一个消息提醒的右上角图标。
            if (mainTab.equals(MainTab.ME)) {
                View cn = indicator.findViewById(R.id.tab_mes);
                mBvNotice = new BadgeView(MainActivity.this, cn);
                mBvNotice.setBadgePosition(BadgeView.POSITION_TOP_RIGHT);
                mBvNotice.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
                mBvNotice.setBackgroundResource(R.drawable.notification_bg);
                mBvNotice.setGravity(Gravity.CENTER);
            }
            mTabHost.getTabWidget().getChildAt(i).setOnTouchListener(this);
        }
    }

Tab页的生成方式

在枚举类中来生成,代码如下:

package net.oschina.app.ui;

import net.oschina.app.R;
import net.oschina.app.fragment.ExploreFragment;
import net.oschina.app.fragment.MyInformationFragment;
import net.oschina.app.viewpagerfragment.NewsViewPagerFragment;
import net.oschina.app.viewpagerfragment.TweetsViewPagerFragment;

public enum MainTab {

    //对应新闻页面
    NEWS(0, R.string.main_tab_name_news, R.drawable.tab_icon_new,
            NewsViewPagerFragment.class),
    //对应动态页面
    TWEET(1, R.string.main_tab_name_tweet, R.drawable.tab_icon_tweet,
            TweetsViewPagerFragment.class),
  //对应快速页面
    QUICK(2, R.string.main_tab_name_quick, R.drawable.tab_icon_new,
            null),
  //对应浏览页面
    EXPLORE(3, R.string.main_tab_name_explore, R.drawable.tab_icon_explore,
            ExploreFragment.class),
  //对应“我”的页面
    ME(4, R.string.main_tab_name_my, R.drawable.tab_icon_me,
            MyInformationFragment.class);

  //该枚举的页面index:0、1、2、3、4
    private int idx;
    //该枚举的页面的资源名字:综合、动弹、快速、发现、我
    private int resName;
    //每个枚举对应的icon
    private int resIcon;
    //每个枚举对应的Fragment的class
    private Class<?> clz;

   //枚举类的构造方法
    private MainTab(int idx, int resName, int resIcon, Class<?> clz) {
        this.idx = idx;
        this.resName = resName;
        this.resIcon = resIcon;
        this.clz = clz;
    }

    public int getIdx() {
        return idx;
    }

    public void setIdx(int idx) {
        this.idx = idx;
    }

    public int getResName() {
        return resName;
    }

    public void setResName(int resName) {
        this.resName = resName;
    }

    public int getResIcon() {
        return resIcon;
    }

    public void setResIcon(int resIcon) {
        this.resIcon = resIcon;
    }

    public Class<?> getClz() {
        return clz;
    }

    public void setClz(Class<?> clz) {
        this.clz = clz;
    }
}

枚举类的学习

枚举类涉及到的方法

  1. ordinal()用来返回枚举值在枚举类中的顺序。

  2. compareTo ()比较两个枚举值的顺序,返回顺序之差。

  3. values(),静态方法,返回包含一个全部枚举值的数组。

  4. toString(),返回枚举常量的名称

  5. valueOf(),返回指定没弄成的枚举类型的枚举常量。

Java中枚举的7中常见用法

常量

在JDK1.5 之前,我们定义常量都是: public static fianl…. 。现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法。

public enum Color {  
  RED, GREEN, BLANK, YELLOW  
}  

switch

JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强。

enum Signal {  
    GREEN, YELLOW, RED  
}  
public class TrafficLight {  
    Signal color = Signal.RED;  
    public void change() {  
        switch (color) {  
        case RED:  
            color = Signal.GREEN;  
            break;  
        case YELLOW:  
            color = Signal.RED;  
            break;  
        case GREEN:  
            color = Signal.YELLOW;  
            break;  
        }  
    }  
}  

向枚举中添加新方法

如果打算自定义自己的方法,那么必须在enum实例序列的最后添加一个分号。而且 Java 要求必须先定义 enum 实例。

public enum Color {  
    RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);  
    // 成员变量 
    private String name;  
    private int index;  
    // 构造方法 
    private Color(String name, int index) {  
        this.name = name;  
        this.index = index;  
    }  
    // 普通方法 
    public static String getName(int index) {  
        for (Color c : Color.values()) {  
            if (c.getIndex() == index) {  
                return c.name;  
            }  
        }  
        return null;  
    }  
    // get set 方法 
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
    public int getIndex() {  
        return index;  
    }  
    public void setIndex(int index) {  
        this.index = index;  
    }  
}  

覆盖枚举的方法

下面给出一个toString()方法覆盖的例子。

public enum Color {  
    RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);  
    // 成员变量 
    private String name;  
    private int index;  
    // 构造方法 
    private Color(String name, int index) {  
        this.name = name;  
        this.index = index;  
    }  
    //覆盖方法 
    @Override  
    public String toString() {  
        return this.index+"_"+this.name;  
    }  
}  

实现接口

所有的枚举都继承自java.lang.Enum类。由于Java 不支持多继承,所以枚举对象不能再继承其他类。

public interface Behaviour {  
    void print();  
    String getInfo();  
}  
public enum Color implements Behaviour{  
    RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);  
    // 成员变量 
    private String name;  
    private int index;  
    // 构造方法 
    private Color(String name, int index) {  
        this.name = name;  
        this.index = index;  
    }  
    //接口方法 
    @Override  
    public String getInfo() {  
        return this.name;  
    }  
    //接口方法 
    @Override  
    public void print() {  
        System.out.println(this.index+":"+this.name);  
    }  
}  

使用接口组织枚举

public interface Food {  
    enum Coffee implements Food{  
        BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO  
    }  
    enum Dessert implements Food{  
        FRUIT, CAKE, GELATO  
    }  
}  

关于枚举集合的使用

java.util.EnumSet和java.util.EnumMap是两个枚举集合。EnumSet保证集合中的元素不重复;EnumMap中的key是enum类型,而value则可以是任意类型。关于这个两个集合的使用就不在这里赘述,可以参考JDK文档。

关于枚举的实现细节和原理请参考:

参考资料:《ThinkingInJava》第四版

参考文章:Java 枚举7常见种用法

你可能感兴趣的:(开源中国)