Activity是android应用的重要组成单元之一(另外3个是Service,BroadcastReceiver和ContentProvider)。实际应用包含了多个Activity,不同的Activity向用户呈现不同的操作界面。Android应用的多个Activity组成Activity栈,当前活动的Activity位于栈顶。对于Android应用而言,Activity主要负责与用户交互,并向用户呈现应用状态。
1 建立、配置和使用Activity
1.1 Activity类简介
- 当一个Activity定义出来后,该Activity类何时被实例化、它所包含的方法何时被调用,这些都不是由开发者来决定,而是Android系统决定
- 创建Activity需要重写一个或者多个方法。其中最常见的就是onCreate方法
- Activity相关类关系视图
- AccountAuthenticatorActivity:实现账户管理界面的Activity
- TabActivity实现Tab界面的Activity
- ListActivity实现列表界面的Activity
- AliasActivity:别名Activity的基类,启动其他Activity时结束自己
- ExpandableListActivity实现可扩展列表界面的Activity
- LauncherActivity:实现Activity列表界面的Activity,当单击列表时,所对应的Activity启动
- PreferenceActivity:实现程序多参数设置,存储界面的Activity
对于Activity的具体子类如ListActivity,LauncherActivity,ExpandableActivity等无需实现具体的布局文件,会自动调用默认布局文件。
示例:PreferenceActivity的使用
Activity文件
import android.preference.PreferenceActivity; import android.preference.PreferenceFragment; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.Button; import android.widget.Toast; import java.util.List; public class PreferenceActivityTest extends PreferenceActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if(hasHeaders()){ Button button = new Button(this); button.setText("设置操作"); setListFooter(button); } } public void onBuildHeaders(List<Header> target){ loadHeadersFromResource(R.xml.preference_headers, target); } public boolean isValidFragment(String fragmentName){ return true;//super.isValidFragment(fragmentName); //return StockPreferenceFragment.class.getName().equals(fragmentName); } public static class Prefs1Fragment extends PreferenceFragment{ @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); } } public static class Prefs2Fragment extends PreferenceFragment{ public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.display_prefs); String website = getArguments().getString("website"); Toast.makeText(getActivity(),"网站域名是:" + website, Toast.LENGTH_SHORT).show(); } } }
Preference主页布局文件
<?xml version="1.0" encoding="utf-8"?> <preference-headers xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 指定启动指定PreferenceFragment的列表项 --> <header android:fragment= "com.example.penghuster.exampletest.PreferenceActivityTest$Prefs1Fragment" android:icon="@drawable/ic_settings_applications" android:title="程序选项设置" android:summary="设置应用的相关选项" /> <!-- 指定启动指定PreferenceFragment的列表项 --> <header android:fragment= "com.example.penghuster.exampletest.PreferenceActivityTest$Prefs2Fragment" android:icon="@drawable/ic_settings_display" android:title="界面选项设置 " android:summary="设置显示界面的相关选项"> <!-- 使用extra可向Activity传入额外的数据 --> <extra android:name="website" android:value="www.crazyit.org" /> </header> <!-- 使用Intent启动指定Activity的列表项 --> <header android:icon="@drawable/ic_settings_display" android:title="使用Intent" android:summary="使用Intent启动某个Activity"> <intent android:action="android.intent.action.VIEW" android:data="http://www.crazyit.org" /> </header> </preference-headers>
Fragment1布局文件
<?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 设置系统铃声 --> <RingtonePreference android:ringtoneType="all" android:title="设置铃声" android:summary="选择铃声(测试RingtonePreference)" android:showDefault="true" android:key="ring_key" android:showSilent="true"> </RingtonePreference> <PreferenceCategory android:title="个人信息设置组"> <!-- 通过输入框填写用户名 --> <EditTextPreference android:key="name" android:title="填写用户名" android:summary="填写您的用户名(测试EditTextPreference)" android:dialogTitle="您所使用的用户名为:" /> <!-- 通过列表框选择性别 --> <ListPreference android:key="gender" android:title="性别" android:summary="选择您的性别(测试ListPreference)" android:dialogTitle="ListPreference" android:entries="@array/gender_name_list" android:entryValues="@array/gender_value_list" /> </PreferenceCategory> <PreferenceCategory android:title="系统功能设置组 "> <CheckBoxPreference android:key="autoSave" android:title="自动保存进度" android:summaryOn="自动保存: 开启" android:summaryOff="自动保存: 关闭" android:defaultValue="true" /> </PreferenceCategory> </PreferenceScreen>
Fragment2布局文件
<?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 设置系统铃声 --> <RingtonePreference android:ringtoneType="all" android:title="设置铃声" android:summary="选择铃声(测试RingtonePreference)" android:showDefault="true" android:key="ring_key" android:showSilent="true"> </RingtonePreference> <PreferenceCategory android:title="个人信息设置组"> <!-- 通过输入框填写用户名 --> <EditTextPreference android:key="name" android:title="填写用户名" android:summary="填写您的用户名(测试EditTextPreference)" android:dialogTitle="您所使用的用户名为:" /> <!-- 通过列表框选择性别 --> <ListPreference android:key="gender" android:title="性别" android:summary="选择您的性别(测试ListPreference)" android:dialogTitle="ListPreference" android:entries="@array/gender_name_list" android:entryValues="@array/gender_value_list" /> </PreferenceCategory> <PreferenceCategory android:title="系统功能设置组 "> <CheckBoxPreference android:key="autoSave" android:title="自动保存进度" android:summaryOn="自动保存: 开启" android:summaryOff="自动保存: 关闭" android:defaultValue="true" /> </PreferenceCategory> </PreferenceScreen>
注意:需要重写PreferenceActivity的isValidFragment方法
1.2 配置Activity
- Android应用要求多有应用程序组件(Activity、Service、ContentProvider、BroadcastReceiver)都必须显式进行配置
- 只需为<application/>元素添加<Activity />子元素即可,另外需要为Activity元素指定一个或者多个intent-filter,该元素用于指定该Activity可以响应的Intent
- 从DDMS查看PreferenceActivity输出的配置文件
1.3 启动关闭Activity
1.3.1 一个Android应用通常会包含多个Activity,但只有一个Activity会作为程序入口-----但Android应用运行时将会自动启动并执行该Activity。其他Activity一般都由入口Activity启动,或者由入口启动的Activity启动,启动Activity的方法有如下两种:
- startActivity(Intent intent):启动其他Activity
- startActivityForResult(Intent intent,int requestCode):以指定的请求码(requestCode)启动Activity,而且程序将会等到新启动Activity的结果(通过重写onActivityResult()方法来获取)
1.3.2 Activity关闭有两个方法:
finish(),结束当前Activity
- finishActivity(int requestCode):结束一startActivityForResult的Activity
1.4 使用Bundle在Activity之间交换数据
当一个Activity启动另一个Activity时,常常会有一些数据需要传过去,Activity之间的数据交换是通过Intent来完成,Intent提供了多个重载的方法来携带额外的数据,主要接口如下:
操作对象 | Intent | Bundle |
发送 |
putExtras( Bundle data) / putExtras(String name, Xxx value) |
putXxx(String key, Xxx data) / putSerializable(String key, Serializable data) |
接收 |
Bundle getextras() / Xxx getXxxExtras(String name) |
Xxx getXxx(String key) / Serializable getSerializable(String key) |
注意:Intent的putExtras方法是智能的,会根据Intent对象内是否存在Bundle对象而自动决定是否需要创建Bundle对象
总结来说,一个有两种方法进行传输数据:
- 利用Intent + 内置Bundle 传输数据方法
发送:Intent intent = new Intent(BundleTest.this,ResultActivity.class); intent.putExtra("person", (Serializable) p);
接收:Intent intent = getIntent(); Person p = (Person)intent.getSerializableExtra("person");
- 利用Intent + 自建Bungle 传输数据方法
发送:Intent intent = new Intent(BundleTest.this,ResultActivity.class); Bundle data = new Bundle();
data.putSerializable("person", p); intent.putExtras(data);
接收:Intent intent = getIntent(); Bundle data = intent.getExtras(); Person p = (Person)data.getSerializable("person");
示例:
发送Activity代码
import org.crazyt.model.Person; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.RadioButton; import java.io.Serializable; public class BundleTest extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button bn = (Button) findViewById(R.id.bn); bn.setOnClickListener(new OnClickListener() { 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(name.getText().toString(), passwd .getText().toString(), gender); //创建一个Bundle对象 Intent intent = new Intent(BundleTest.this, ResultActivity.class); //1、利用Intent + 内置Bundle 传输数据方法 // intent.putExtra("person", (Serializable) p); //2 、利用Intent + 自建Bungle 传输数据方法 Bundle data = new Bundle(); data.putSerializable("person", p); intent.putExtras(data); //启动intent对应的Activity startActivity(intent); } }); } }
接收Activity代码
import org.crazyt.model.Person; public class ResultActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.result); TextView name = (TextView) findViewById(R.id.name); TextView passwd = (TextView) findViewById(R.id.passwd); TextView gender = (TextView) findViewById(R.id.gender); // 获取启动该Result的Inten Intent intent = getIntent(); //直接利用Intent传输数据方法1 // Person p = (Person) intent.getSerializableExtra("person"); //直接利用Intent传输数据方法2 Bundle data = intent.getExtras(); Person p = (Person) data.getSerializable("person"); name.setText("您的用户名为:" + p.getName()); passwd.setText("您的密码为:" + p.getPass()); gender.setText("您的性别为:" + p.getGender()); } }
效果图
点击注册->
1.5 启动其他Activity并返回结果
简单地讲,就是当前Activity1启动另一个Activity2,Activity1需要获得Activity2的运行结果;而这也是通过Bundle进行数据交换的,为了获取被启动的Activity所返回的结果,需要从两方面入手:
- 当前Activity需要重写onActivityResult(int requestCode, int resultCode, Intent intent),当被启动的Activity返回结果时,该方法将会被触发
- 被启动的Activity需要调用setResult()方法设置处理结果
示例:
启动Activity代码
import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.TextView; import org.crazyt.model.Person; public class ResultActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.result); } public void click(View view){ Intent intent = new Intent(ResultActivity.this, BundleTest.class); startActivityForResult(intent,0); } public void onActivityResult(int requestCode, int resultCode, Intent intent){ if (requestCode == resultCode){ Bundle data = intent.getExtras(); Person result = (Person)data.getSerializable("person"); TextView name = (TextView) findViewById(R.id.name); TextView passwd = (TextView) findViewById(R.id.passwd); TextView gender = (TextView) findViewById(R.id.gender); name.setText("您的用户名为:" + result.getName()); passwd.setText("您的密码为:" + result.getPass()); gender.setText("您的性别为:" + result.getGender()); } } }
操作Activity代码
import org.crazyt.model.Person; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.RadioButton; import java.io.Serializable; public class BundleTest extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button bn = (Button) findViewById(R.id.bn); bn.setOnClickListener(new OnClickListener() { 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(name.getText().toString(), passwd .getText().toString(), gender); Intent intent = getIntent(); Bundle data = new Bundle(); data.putSerializable("person", p); intent.putExtras(data); BundleTest.this.setResult(0, intent); BundleTest.this.finish(); } }); } }
效果图
-->-->