Activity的基础知识

前言

长风破浪会有时,直挂云帆济沧海。

关于Activity的启动和关闭

一个Android应用程序通常都包含多个Activity,但只有一个Activity会作为程序的入口——当该Android应用运行时将会自动启动并执行该Activity。至于应用中的其他Activity,通常都由入口Activity启动,或由入口Activity启动的Activity启动。
Activity启动其他Activity有如下两个方法。
  • startActivity(Intent intent):启动其他Activity。

  • startActivityForResult(Intent intent,int requestCode):以指定的请求码(requestCode)启动Activity,而且程序将会获取新启动的Activity返回的结果(通过重写OnActivityResult(...)方法)。

上面两个方法都用到了Intent参数,Intent是Android应用里各组件之间同通信的重要方式,一个Activity通过Intent来表达自己“意图”——想要启动哪个组件,被启动的组件既可是Activity组件,也可是Service组件。
Android为关闭Activity准备了如下两个方法。
  • finish():结束当前Activity。

  • finishActivity(int requestCode):结束以startActivityForResult(Intent intent,int requestCode)方法启动的Activity。

代码示例

FirstActivity.java
public class FirstActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);
        Button bt = (Button) findViewById(R.id.bt);
        bt.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                //创建需要启动的Activity对应的Intent
                Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
                //启动intent对应的Activity
                startActivity(intent);
            }
        });
    }
}

SecondActivity.java
public class SecondActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.seconde_layout);
        Button back = (Button) findViewById(R.id.back);
        Button back_finish = (Button) findViewById(R.id.back_finish);

        back.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                //创建需要启动的Activity对应的Intent
                Intent intent = new Intent(SecondActivity.this,FirstActivity.class);
                //启动intent对应的Activity
                startActivity(intent);
            }
        });

        back_finish.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                //创建需要启动的Activity对应的Intent
                Intent intent = new Intent(SecondActivity.this,FirstActivity.class);
                //启动intent对应的Activity
                startActivity(intent);
                //结束当前Activity
                finish();
            }
        });
    }
}

提示

上述程序的布局文件就只包含简单的按钮来实现跳转,第二个Activity唯一的区别就是finish()方法,它表明该Activity会结束自己。

使用Bundle在Activity之间交换数据

当一个Activity启动另一个Activity时,常常会有一些数据需要传过去。这时Intent就相当于一个“信使”,我们将需要传送的数据存入Intent中即可。、
Intent提供了多个方法来“携带”额外的数据,如下所示。
  • putExtras(Bundle data):向Intent中放入需要“携带”的数据包。

  • Bundle getExtras():取出Intent中所“携带”的数据包。

  • putExtra(String name,Xxx value):向Intent中按key-value对的形式存入数据。

  • getXxxExtra(String name):从Intent中按key取出指定类型的数据。

上述方法中的Bundle就是一个简单的数据携带包,该Bundle对象包含了多个方法来存入数据。
  • putXxx(String key, Xxx value):向Bundle中放入Int、Long等各种类型的数据。

  • putSerializable(String key, Serializable data):向Bundle中放入一个可序列化的对象。

  • getXxx(String key):从Bundle中取出Int、Long等各种类型的数据。

  • getSerializable(String key):从Bundle中取出一个可序列化的对象。

下面我通过一个实例来介绍Activity之间如何通过Bundle交换数据。
本程序包含两个Activity,其中第一个Activity用于收集用户的输入信息,当用户单击该Activity的“注册”按钮时,应用进入第二个Activity,第二个Activity将会获取第一个Activity中的数据。

代码示例

FirstActivity.java
public class FirstActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);

        Button bn = (Button) findViewById(R.id.bn);
        bn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                EditText name = (EditText) findViewById(R.id.name);
                EditText passwd = (EditText) findViewById(R.id.passwd);
                RadioButton male = (RadioButton) findViewById(R.id.male);
                String gender = male.isChecked() ? "男" : "女";
                Person p = new Person();
                p.setName(name.getText().toString());
                p.setPasswd(passwd.getText().toString());
                p.setGender(gender);

                //创建一个Bundle对象
                Bundle data = new Bundle();
                data.putSerializable("person", p);
                //创建一个Intent
                Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
                intent.putExtras(data);
                //启动intent对应的Activity
                startActivity(intent);
            }
        });
    }
}

first_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="请输入您的注册信息"
        android:textSize="20sp" />

    <TableRow>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="用户名:"
            android:textSize="16sp" />

        <EditText
            android:id="@+id/name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="请填写想注册的账号"
            android:selectAllOnFocus="true" />
    </TableRow>

    <TableRow>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="密码:"
            android:textSize="16sp" />

        <EditText
            android:id="@+id/passwd"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:password="true"
            android:selectAllOnFocus="true" />
    </TableRow>

    <TableRow>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="性别:"
            android:textSize="16sp" />
        <RadioGroup
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >

            <RadioButton
                android:id="@+id/male"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="男"
                android:textSize="16sp"
                />
            <RadioButton
                android:id="@+id/female"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="女"
                android:textSize="16sp"
                />
        </RadioGroup>
    </TableRow>
    <Button
        android:id="@+id/bn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="注册"
        android:textSize="16sp"
        />
</TableLayout>
SecondActivity.java
public class SecondActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.seconde_layout);

        TextView name = (TextView) findViewById(R.id.name);
        TextView passwd = (TextView) findViewById(R.id.passwd);
        TextView gender = (TextView) findViewById(R.id.gender);
        //获取启动该Activity的Intent
        Intent intent = getIntent();
        //直接通过Intent取出它所携带的Bundle数据包中的数据
        Person p = (Person) intent.getSerializableExtra("person");
        name.setText("您的用户名为:" + p.getName());
        passwd.setText("您的密码为:" + p.getPasswd());
        gender.setText("您的性别为:" + p.getGender());
    }
}
seconde_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    >

    <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        />
    <TextView
        android:id="@+id/passwd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        />
    <TextView
        android:id="@+id/gender"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        />

</LinearLayout>

效果

[图片上传失败...(image-e4b6ea-1514096470518)]
[图片上传失败...(image-2ca6b1-1514096470519)]

提示

需要传送数据如果是对象,这个对象应该实现Serializable接口。

启动其他Activity并返回结果

前面已经提到,Activity还提供了一个startActivityForResult(Intent intent,int requestCode)方法来启动其他Activity。该方法用于启动指定Activity,而且期望获取指定Activity返回的结果。这种情况很常见,例如应用程序第一个界面需要用户进行选择,但需要选择的列表数据比较复杂,必须启动另一个Activity让用户选择。当用户在第二个Activity中选择完成后,程序返回第一个Actvity,第一个Activity必须能获取并显示用户在第二个Activity中选择的结果。在这种应用场景下,也通过Bundle进行数据交换的。
为了获取被启动的Activity所返回的结果,需要从两方面着手。
  • 当前Activity需要重写onActivityResult(int requestCode,int resultCode,Intent intent),当被启动的Activity返回结果时,该方法会被触发,其中requestCode代表请求码,而resultCode代表Activtiy返回的结果码,由开发者自行设定。

  • 被启动的Activtiy需要调用setResult()方法设置处理结果。

一个Activity中可能包含多个按钮,并调用多个startActivityForResult()方法来打开多个不同的Activity处理不同的业务,当这些新Activity关闭后,系统将回调前面Activity的onActivityResult(int requestCode,int resultCode,Intent data)方法。为了知道该方法是由哪个请求的结果所触发的,可利用requestCode请求码;为了知道返回的数据来自于哪个新的Activity,可利用resultCode结果码。

代码示例

FirstActivity.java
public class FirstActivity extends Activity {

    Button bt;
    EditText city;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);

        bt = (Button) findViewById(R.id.bt);
        city = (EditText) findViewById(R.id.city);

        bt.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                //创建需要对应于目标Activity的Intent
                Intent intent = new Intent(FirstActivity.this, SelectCityActivity.class);
                //启动指定Activity并等待返回的结果,其中0是请求码,用于标识该请求
                startActivityForResult(intent, 0);
            }
        });
    }

    //重写该方法,该方法以回调的方式来获取指定Activity返回的结果
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {

        //当requestCode、resultCode同时为0时,也就是处理特定的结果
        if(requestCode == 0 && resultCode == 0)
        {
            //取出Intent里德Extras数据
            Bundle data = intent.getExtras();
            //取出Bundle中的数据
            String resultCity = data.getString("city");
            //修改city文本框的内容
            city.setText(resultCity);
        }
    }
}
SelectCityActivity.java
public class SelectCityActivity extends ExpandableListActivity {

    //定义省份数组
    private String[] provinces = new String[]
    {"广西","广东","湖南","云南"};

    private String[][] cities = new String[][]
    {
        {"桂林","柳州","南宁","北海"},
        {"广州","深圳","珠海","中山"},
        {"长沙","岳阳","衡阳","株洲"},
        {"昆明","玉溪","大理","丽江"}
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ExpandableListAdapter adapter = new BaseExpandableListAdapter() {

            @Override
            public boolean isChildSelectable(int groupPosition, int childPosition) {
                return true;
            }

            @Override
            public boolean hasStableIds() {
                return true;
            }

            private TextView getTextView() {
                AbsListView.LayoutParams lp = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 64);
                TextView textView = new TextView(SelectCityActivity.this);
                textView.setLayoutParams(lp);
                textView.setGravity(Gravity.CENTER_VERTICAL|Gravity.LEFT);
                textView.setPadding(36, 0, 0, 0);
                textView.setTextSize(20);
                return textView;
            }

            @Override
            public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {

                LinearLayout ll = new LinearLayout(SelectCityActivity.this);
                ll.setOrientation(LinearLayout.HORIZONTAL);
                ImageView logo = new ImageView(SelectCityActivity.this);
                logo.setImageResource(R.drawable.ic_launcher);
                ll.addView(logo);
                TextView textView = getTextView();
                textView.setText(getGroup(groupPosition).toString());
                ll.addView(textView);
                return ll;
            }

            @Override
            public long getGroupId(int groupPosition) {
                return groupPosition;
            }

            @Override
            public int getGroupCount() {
                return provinces.length;
            }

            @Override
            public Object getGroup(int groupPosition) {
                return provinces[groupPosition];
            }

            @Override
            public int getChildrenCount(int groupPosition) {
                return cities[groupPosition].length;
            }

            @Override
            public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView,
                    ViewGroup parent) {
                TextView textView = getTextView();
                textView.setText(getChild(groupPosition, childPosition).toString());
                return textView;
            }

            @Override
            public long getChildId(int groupPosition, int childPosition) {
                // TODO Auto-generated method stub
                return childPosition;
            }

            @Override
            public Object getChild(int groupPosition, int childPosition) {
                // TODO Auto-generated method stub
                return cities[groupPosition][childPosition];
            }
        };

        setListAdapter(adapter);
        //为列表项设置监听
        getExpandableListView().setOnChildClickListener(new OnChildClickListener() {

            @Override
            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {

                //获取启动该Activity之前的Activity对应的Intent
                Intent intent = getIntent();
                intent.putExtra("city", cities[groupPosition][childPosition]);
                //设置该SelectCityActivity的结果码,并设置结束之后退回的Activity
                SelectCityActivity.this.setResult(0, intent);
                //结束SelectCityActivity
                SelectCityActivity.this.finish();
                return false;
            }
        });
    }
}

效果

Screenshot_20171101-145622.png

Screenshot_20171101-145711.png
Screenshot_20171101-145743.png

提示

别忘记每创建一个新的Activity,都要去清单文件里注册这个Activity。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容