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。