- Activity 是Android 四大组件之一,它用于展示界面。
- 是一个负责与用户交互的组件,可以通过setContentView(View)来显示指定控件。
- Activity 之间通过Intent 进行通信。### Activity之间的跳转
Activity清单配置
- 定义类继承Activity
- 在AndroidManifest.xml 的节点中声明
application中lable指程序的名字,
activity中的lable是指activity 的名字
name 属性::包名.Activity 类名
包名如果与mainfest 的package 一致,可以用“.”代替。或者不写
Intent-filter 子节点:
- 添加意图过滤,可以通过隐式意图启动。
- 可以在桌面生成快捷方式,应用程序的入口
如果此activity还指定了以下filter那么这个界面就会在桌面创建快捷方式
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
Icon 属性:图标
theme 属性:指定主题
Activity 之间的跳转
显式意图跳转
- 可以引用到那个类, 并且可以引用到那个类的字节码时可以使用。
- 一般用于自己程序的内部。显式跳转不可以跳转到其他程序的页面中。
隐式意图跳转
- 可以在当前程序跳转到另一个程序的页面
- 隐式跳转不需要引用到那个类,但是必须得知道那个界面的动作(action)和信息(category)。
使用Intent意图传递数据
Activity 之间通过Intent 进行通信。Intent 即意图,用于描述一个页面的信息,同时也是一个数据的载体。
- 案例 RP计算器
public class MainActivity extends Activity {
private EditText et_name;
private RadioGroup rg_group;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_name = (EditText) findViewById(R.id.et_name);
rg_group = (RadioGroup) findViewById(R.id.radioGroup1);
}
// 点击按钮 实现计算人品 跳转到ResultActivity页面
public void click(View v) {
// [1]获取用户名
String name = et_name.getText().toString().trim();
// [2] 判断一下name 是否为空
if (TextUtils.isEmpty(name)) {
Toast.makeText(getApplicationContext(), "亲 请输入姓名", 1).show();
return;
}
// [3]判断用户选择的性别
int radioButtonId = rg_group.getCheckedRadioButtonId();
int sex = 0;
switch (radioButtonId) {
case R.id.rb_male: // 代表选择的是男
sex = 1;
break;
case R.id.rb_female: // 代表选择的是女
sex = 2;
break;
case R.id.rb_other: // 代表选择的是人妖
sex = 3;
break;
}
if(sex == 0){
Toast.makeText(getApplicationContext(), "请选择性别", 1).show();
return;
}
//[4]跳转到ResultActivity页面 用显示意图跳转
Intent intent = new Intent(this, ResultActiviyt.class);
//传递姓名
intent.putExtra("name", name);
//传递性别
intent.putExtra("sex", sex);
startActivity(intent);
}
}
跳转页
public class ResultActiviyt extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// [1]加载布局
setContentView(R.layout.activity_result);
TextView tv_name = (TextView) findViewById(R.id.tv_name);
TextView tv_sex = (TextView) findViewById(R.id.tv_sex);
TextView tv_result = (TextView) findViewById(R.id.tv_result);
// [2]获取mainActivity 传递过来的数据
Intent intent = getIntent(); // 获取开启此Activity的意图对象
// [3]获取name 和 sex 的值 小技巧 :传递的是什么数据类型 这边就按照传递的数据类型取
String name = intent.getStringExtra("name");
int sex = intent.getIntExtra("sex", 0);
// [4]根据name 和 sex 显示数据
tv_name.setText(name);
byte[] bytes = null;
// [5]显示性别
try {
switch (sex) {
case 1:
tv_sex.setText("男");
bytes = name.getBytes("gbk");
break;
case 2:
tv_sex.setText("女");
bytes = name.getBytes("utf-8");
break;
case 3:
tv_sex.setText("人妖");
bytes = name.getBytes("iso-8859-1");
break;
default:
break;
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//[6]计算人品结果 市面上大多数应用采用的是随机数
int total = 0;
for (byte b : bytes) { // 0001 1111
int number = b&0xff; // 1111 1111
total+=number;
}
// 获取得分
int score = Math.abs(total)%100;
if (score > 90) {
tv_result.setText("您的人品非常好,您家的祖坟都冒青烟啦");
}else if (score > 80) {
tv_result.setText("您的人品还可以 ");
}else if (score > 60) {
tv_result.setText("您的人品刚及格");
}else{
tv_result.setText("您的人品太次了 您需要努力啊");
}
}
}
案例 短信发送器 (请求码,结果码)
- requestCode 开启activity时设置的请求吗
- resultCode 在目标activity中设置的结果码
主页面
public class MainActivity extends Activity {
private EditText et_number;
private EditText et_content;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//[1]找到我们关心的控件
et_number = (EditText) findViewById(R.id.et_number);
et_content = (EditText) findViewById(R.id.et_content);
}
//点击按钮跳转到发送短信模板页面
public void insertsms(View v){
Intent intent = new Intent(this,SmsTemplateActivity.class);
startActivityForResult(intent, 2);
}
//点击按钮 跳转到ContactActivity 页面
public void add(View v){
Intent intent = new Intent(this,ContactActivity.class);
// startActivity(intent);
//小细节 如果点击按钮 开启了另外一Activity 并且当开启的这个Activity关闭的时候 我想要这个开启Activity的数据 用下面这个方法开启activity
startActivityForResult(intent, 1);
}
//当我们开启的Activity 页面关闭的时候 这个方法就调用
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode==1) {
//代表请求ContactActivity这个页面的数据
String phone = data.getStringExtra("phone");
et_number.setText(phone);
}else if (requestCode == 2) {
//代表请求 短信模板页面的数据
String smsContent = data.getStringExtra("smscontent");
et_content.setText(smsContent);
}
/*
if (resultCode == 10) {
//说明数据是从 ContactActivity 返回
String phone = data.getStringExtra("phone");
et_number.setText(phone);
}else if (resultCode == 20) {
//说明数据 是从 SmsTempate 返回
String smsContent = data.getStringExtra("smscontent");
et_content.setText(smsContent);
}
*/
super.onActivityResult(requestCode, resultCode, data);
}
//点击按钮 发送短信
public void send(View v){
//[1]获取发送短信的号码 和 发送的内容
String number = et_number.getText().toString().trim();
String content = et_content.getText().toString().trim();
//[2]获取到smsmanager的实例
SmsManager smsManager = SmsManager.getDefault();
ArrayList<String> divideMessages = smsManager.divideMessage(content);
for (String div : divideMessages) {
/**
* destinationAddress 发送给谁
* scAddress 服务中心号码
*
* text 要发送的内容
*/
smsManager.sendTextMessage(number, null, div, null, null);
}
}
}
获取联系人页面
public class ContactActivity extends Activity {
private List<Person> lists;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//加载布局
setContentView(R.layout.activity_contact);
//[1]找到控件
ListView lv = (ListView) findViewById(R.id.lv);
//[2]准备listview 要显示的数据 模拟点假数据
lists = new ArrayList<Person>();
for (int i = 0; i < 20; i++) {
Person p = new Person();
p.setName("张三"+i);
p.setPhone("11"+i);
lists.add(p);
}
//[3]展示数据
lv.setAdapter(new MyAdapter());
//[4]给listview 设置点击事件
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//[5]获取我点中条目的数据 数据在哪里面存着呢 就去哪里取
String phone = lists.get(position).getPhone();
//[5.0]把数据返回给调用者
Intent intent = new Intent();
intent.putExtra("phone", phone);
//把结果返回给调用者
setResult(10, intent);
//[5.1]关闭当前页面
finish();
}
});
}
@Override
public void onBackPressed() {
super.onBackPressed();
}
private class MyAdapter extends BaseAdapter{
@Override
public int getCount() {
return lists.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) {
view = View.inflate(getApplicationContext(), R.layout.contact_item, null);
}else {
view = convertView;
}
//[1]找到我们在item 中定义的控件 用来显示 数据
TextView tv_name = (TextView) view.findViewById(R.id.tv_name);
TextView tv_phone = (TextView) view.findViewById(R.id.tv_phone);
//[2]展示数据
tv_name.setText(lists.get(position).getName());
tv_phone.setText(lists.get(position).getPhone());
return view;
}
}
}
获取短信模板页
public class SmsTemplateActivity extends Activity {
String objects[] = {"我在吃饭,请稍后联系","我在开会,请稍后联系","我在上课,请稍后联系","我在打代码,请稍后联系","我在约会,请稍后联系"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_smstemplate);
//[1]找到lv
ListView lv = (ListView) findViewById(R.id.lv);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getApplicationContext(), R.layout.smstemplate_item, objects);
//[2]显示数据
lv.setAdapter(adapter);
//[3]设置lv 的条目的点击事件
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//[4]取出点击条目的数据
String smsContent = objects[position];
//[5]把smsContent 返回调用者
Intent intent = new Intent();
intent.putExtra("smscontent", smsContent);
setResult(20, intent);
//[6]调用finish
finish();
}
});
}
}
Activity生命周期
Activity 有三种状态:
- 1、当它在屏幕前台时,响应用户操作的Activity, 它是激活或运行状态
- 2、当它上面有另外一个Activity,使它失去了焦点但仍然对用户可见时, 它处于暂停状态。
- 3、当它完全被另一个Activity 覆盖时则处于停止状态。
当Activity 从一种状态转变到另一种状态时,会调用以下保护方法来通知这种变化:
方法名 | 说明 |
---|---|
void onCreate() | 设置布局以及进行初始化操作 |
void onStart() | 可见, 但不可交互 |
void onRestart() | 调用onStart() |
void onResume() | 可见, 可交互 |
void onPause() | 部分可见, 不可交互 |
void onStop() | 完全不可见 |
void onDestroy() | 销毁 |
图
- startActivity 开启一个Activity 时, 生命周期的过程是:
onCreate ->onStart(可见不可交互) ->onResume(可见可交互) - 点击back 键关闭一个Activity 时, 生命周期的过程是:
onPause(部分可见不可交互)->onStop(完全不可见)->onDestroy(销毁) - 当开启一个新的Activity(以对话框形式), 新的activity 把后面的activity 给盖住一部分时, 后面的activity 的生命周期执行的方法是:
onPause(部分可见, 不可交互)
Activity 以对话框的形式显示,需在activity 节点追加主题android:theme=”@android:style/Theme.Dialog” - 当把新开启的Activity(以对话框形式)给关闭时, 后面的activity 的生命周期执行的方法是:
onResume(可见, 可交互) - 当开启一个新的activity 把后面的activity 完全盖住时, 生命周期的方法执行顺序是:
onPause ->onStop(完全不可见) 当把新开启的activity(完全盖住)给关闭时, 生命周期的方法执行顺序是:
onRestart ->onStart ->onResume(可见, 可交互)实际工作中常用的方法以及应用场景有:
onResume 可见, 可交互.。把动态刷新的操作启动。
onPause 部分可见, 不可交互. 把动态刷新的一些操作, 给暂停了。
onCreate 初始化一些大量的数据。
onDestroy 把数据给释放掉, 节省内存。
横竖屏切换
横竖屏切换时,默认情况下会把activity 先销毁再创建,这个体验是非常差的
不让Activity 在横竖屏切换时销毁,只需要在清单文件声明Activity 时配置节点的几个属性即可
兼容所有版本:
android:configChanges="orientation|keyboardHidden|screenSize
禁止横竖屏:
screenOrientation=”” 指定屏幕固定方向,不会随着屏幕旋转而旋转
android:screenOrientation=”portrait” 始终竖屏
android:screenOrientation=”landscape” 始终横屏
Activity任务栈
- 程序打开时就创建了一个任务栈, 用于存储当前程序的activity,所有的activity 属于一个任务栈。
- 一个任务栈包含了一个activity 的集合, 去有序的选择哪一个activity 和用户进行交互:只有在任务栈栈顶的activity 才可以跟用户进行交互
- 任务栈可以移动到后台, 并且保留了每一个activity 的状态. 并且有序的给用户列出它们的任务, 而且还不丢失它们状态信息
- 退出应用程序时:当把所有的任务栈中所有的activity 清除出栈时,任务栈会被销毁,程序退出。
重复数据太多, 会导致内存溢出的问题(OOM)
Activity启动模式
为了解决任务栈产生的问题,Android 为Activity 设计了启动模式
可以在AndroidManifest.xml 配置的android:launchMode 属性为以下四种之一即可。
四种launchMode:
1.standard
默认模式
2.singleTop
如果任务栈的栈顶存在这个要开启的activity,不会重新的创建activity,而是复用已经存在的activity。保证栈顶如果存在,不会重复创建。
应用场景:浏览器的书签
3.singleTask
单一任务栈,在当前任务栈里面只能有一个实例存在,
当开启activity的时候,就去检查在任务栈里面是否有实例已经存在,
如果有实例存在就复用这个已经存在的activity,
并且把这个activity上面的所有的别的activity都清空,
复用这个已经存在的activity。保证整个任务栈里面只有一个实例存在
应用场景:浏览器的activity
4.singleInstance
activity会运行在自己的任务栈里面,并且这个任务栈里面只有一个实例存在
如果你要保证一个activity在整个手机操作系统里面只有一个实例存在,使用singleInstance
应用场景: 来电页面