-
android:id=:@+id/remove_item"
android:title="Remove"/>
- 标签创建具体菜单项,android:id给出唯一标识符,android:title给这个菜单项指定名称
在FirstActivity中覆写onCreateOptionsMenu()方法(可使用Ctrl+O快捷键):
public boolean onCreatOptionMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
getMenuInflater()得到MenuInflater对象
调用MenuInflater的inflate()方法创建菜单。
inflate()两个参数:
第一个参数用于指定通过那个资源文件来创建菜单
第二个指定我们的菜单项将添加到那个Menu对象中
返回值true表示允许创建的菜单显示出来,false表示无法显示
菜单功能创建:
在FirstActivity中覆写onOptionsItemSelected()方法:
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.add_item:
Toast.makeText(this, "You clicked Add", Toast.LENGTH_SHORT).show();
break;
case R.id.remove_item:
Toast.makeText(this, "Yout clicked Remove", Toast.LENGTH_SHORT).show();
break;
default:
}
return true;
}
在onOptionsItemSelected()方法中通过item.getItemId() 判断点击的菜单项
6、销毁一个活动
Back键可以销毁当前活动
在活动中调用finish()方法也可以销毁当前活动,效果与Back一样
3、使用Intent在活动中穿梭
活动之间的跳转与数据的传输
Intent大致分为两种:显式Intent和隐式Intent
1、使用显式Intent
Intent有多个构造函数的重载
构造函数:Intent(Context packageContext, Class>cls):
第一个参数Context指启动活动的上下文,比如FirstActivity.this
第二个参数Class是指想要启动的目标活动,比如SecondActivity.class
Intent的使用:
startActivity(intent):intent是先构造完成的Intent对象
Activty类中的方法:startActivity()方法
具体代码:
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
}
以上就实现了由FirstActivity跳转到SecondeActivity的功能
2、使用隐式Intent
不明确指定要启动哪一个活动
隐式Intent的本质是通过XxxxActivity.java文件中的Intent对象所携带的action与category等与清单文件AndroidManifest.xml中
标签里的、等相匹配来决定哪些活动能响应.java文件中的Intent对象
Ps:另有博客讲述隐式Intent匹配原则。
AndroidManifest.xml代码如下:
FirstActivity中按钮点击事件代码:
button1.setOnclickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.activitytest.ACTION_START");
startActivity(intent);
}
});
另一种Intent构造函数
android.intent.category.DEFAULT是Intent的默认category,在调用startActivity()时会自动加入这个category
每个Intent只能指定一个action,能指定多个category
3、更多隐式Intent用法
使用隐式Intent不仅可以启动自己程序内的活动,还可以启动其他程序的活动
这帮助Android实现了多应用之间的功能共享
应用程序中展示一个网页:
FristActivity按钮点击事件onClick中代码:
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com")); 这是关键部分
startActivity(intent);
}
指定Intent的action是Intent.ACTION_VIEW,只是一个Android系统内置动作,其常量值为android.intent.action.VIEW
Uri.parse()方法把字符串解析为Uri对象
setData方法接收Uri对象
在标签中再配置标签,用于更精确的指定当前活动能够响应什么类型的数据
标签中主要配置以下内容:
android:scheme 用于指定数据的协议部分,如http
android:host 用于指定数据的主机名, 如www.baidu.com
android:port 用于指定数据的端口邠,一般紧随主机名之后
android:path
android:mineType
只有标签中指定内容和Intent中携带的Data完全一致时,活动才能响应该Intent
一般在标签中不会指定过多内容,如上面只指定android:scheme为http,就可以响应所有http协议的Intent:
除了http协议外还有geo表示地理位置、tel表示拨打电话:
intent.setData(Uri.parse("tel:10086"));
4、向下一个活动传递数据
Intent提供 putExtar()方法的重载,可以把数据暂存在Intent中
intent.putExtra("extra_data", data):
第一个参数是键,第二个参数是真正要传递的数据
public void onClick(View v) {
String data = "xxxx";
Intent intent = new Intent(FirstActivit.this, SecondActivity.class);
intent.putExtra("extra_data", data);
startActivity(intent);
}
取出数据:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");
}
getIntent()方法获取Intent对象
getXxxExtra()传入参数为键,获得相应的数据,具体有getIntExtra()、getBooleanExtra()等
5、返回数据给上一个活动
主要通过startActivityForResult()启动活动,通过setResult()设置返回的请求码与Intent,通过onActivityResult()获得返回的数据
a、Activity中有一个startActivityForResult()方法也可以启动活动,这个方法 期望 在 活动销毁 的时候能返回一个结果给上一个活动
startActivitForResult(intent, 1)方法的参数:第一个参数是Intent,第二个参数是请求码requestCode,用于判断数据来源
b、SecondActivity中onClick()://Ps:这是通过按钮回到启动活动,所以覆写按钮监听方法
public void onClick(View v) {
Intent intent = new Intent();
intent.putExtra("data_return", "Hello FirstActivity");
setResult(RESULT_OK, intent);
finish();
}
setResult()方法专门用于向上一个活动返回数据,接收两个参数:
第一个用于返回处理结果resultCode,一般是RESULT_OK或RESULT_CANCELED
第二个把带有数据的Intent对象传递回去
c、使用startActivityForResult()启动活动时,在活动被销毁后会回调上一个活动的onActivityResult()方法,所以需要在第一个活动中覆写这个方法来得到数据
@Override
protected void onActivityResult(int requestCode, inte resultCode, Intent data) {
switch (reqeustCode) {
case 1:
if (resultCode == RESULT_OK) {
String returnedData = data.getStringExtar("data_return");
}
break;
default:
}
}
Ps:关于break的问题:break可用可不用,没有break时顺序执行,直到遇到break跳出或者执行到末尾
onActivityResult()三个参数:
第一个参数requestCode,即我们在启动活动中传入的请求码
第二个参数resultCode,即我们在返回数据时传入的处理结果
第三个参数,即携带返回数据的Intent对象
requestCode判断数据来源,resultCode判断处理结果是否成功
如果用户是通过Back键回到启动活动,可以通过覆写onBackPressed()方法来解决问题
4、活动的生命周期
1、返回栈
Android中的活动是可以层叠的,每启动一个新的活动,就会覆盖在原来的活动智商,点击Back会销毁最上面的活动,下面的活动就会重新显示出来
Android使用任务(Task)来管理活动,一个任务就是一组存放在栈里的活动的集合,这个栈也被称作返回栈(Back Stack)
默认情况下,每当我们启动一个新的活动,它会在返回栈中入栈,并处于栈顶的位置。每当我们按下Back或者调用finish()方法销毁一个方法时,处于栈顶的活动就会出栈,前一个活动就会重新处于栈顶,系统总是会显示处于栈顶的活动给用户。
返回栈管理活动入栈出栈操作:
2、活动状态
每个活动在其生命周期中最多可能会有4种状态
运行状态:
当活动位于栈顶时,活动就处于运行状态。
系统最不愿意回收运行状态的活动
暂停状态:
当一个活动不再位于栈顶,但仍然可见时,活动就处于暂停状态。
仍然可见是指:并不是所有的活动都占满整个屏幕,比如对话框形式的活动,它只占用屏幕中间一部分。
暂停状态活动仍然是完全存活着的,系统次不愿意回收
停止状态:
当一个活动不再处于栈顶,并且完全不可见的时候,活动处于停止状态。
系统仍然为该活动保存相应的状态和成员变量。
系统第三不愿意回收
销毁状态:
活动从返回栈中移除后,活动就变成销毁状态。
系统最倾向于回收销毁状态的活动
3、活动的生存期
Activity类有7个回调方法,覆盖了活动生命周期的每一个环节。
7个回调方法:
onCreate():
活动第一次被创建时调用
完成活动的初始化操作
onStart():
活动由不可见变为可见时调用
onResume():
活动准备好和用户交互时调用
活动一定是位于栈顶的,并处于运行状态
onPause():
系统准备去启动或者恢复另一个活动的时候调用
释放小号的CPU资源,保存一些关键数据
执行速度要快,不能影响新的栈顶活动
onStop():
活动完全不可见的时候调用
与onPasue()的区别在于,新启动的活动如果是对话框形式的话,onPause()会被调用,而onStop()不会被执行
onDestroy():
活动被销毁前调用,之后活动的状态变为销毁状态
onRestart():
活动由停止状态变为运行状态时调用
三种生存期:
完整生存期:
onCreate()和onDestroy()方法之间所经历的。onCreate()完成初始化,onDestroy()完成内存释放
可见生存期:
onStart()和onStop()方法之间所经历的。
在此期间,活动对于用户总是可见的
onStart()中对资源进行加载,onStop()中对资源进行释放
前台生存期:
onResume()和onPause()方法之间所经历的。
此时,活动总是处于运行状态,可以和用户进行交互
活动生命周期示意图:
3、体验活动的生命周期
android:theme=”@style/Theme.AppCompat.Dialog”:
android:theme属性,是用于给当前活动指定主题的,Android系统内置很多主题
4、活动被回收的解决办法
Activity提供了一个onSaveInstanceState()回调方法
这个方法可以保证在活动被回收之前一定会被调用
在onSaveInstanceState()方法中保存数据:
该方法提供一个Bundle类型参数
Bundle提供一系列方法保存数据,比如:
putString()保存字符串
putInt()保存整数
每个保存方法传入两个参数:
一个参数是键
一个是保存的值
代码如下:
@Override
Protected void onSaveInstanceState(Bundle outState) {
Super.onSaveInstanceState(outState);
String tempData = “Something you just typed”;
outState.putString(“data_key”, tempData);
}
onCreate()方法也有一个Bundle类型参数,一般为null,但如果onSaveInstanceStae()方法被调用过,则该Bundle参数就会带有之前保存的全部数据
Bundle与Intent保存和取出数据的方法对比:
Bundle保存:bundle.put类型名(“键名”, 值)
Intent保存:intent.putExtra(“键名”, 值)
Bundle取出:bundle.get类型名(“键名”)
Intent取出:intent.get类型名(“键名”)
Intent还可以和Bundle结合使用:
使用Bundle保存数据,再用Intent保存Bundle
5、活动的启动模式
四种启动模式:
standard
singleTop
singleTask
singleInstance
在AndroidManifest.xml中通过标签指定android:launcherMode属性来选择启动模式
1、Standard
默认启动模式
每次启动都会创建该活动的一个新的实例
示意图:
2、singleTop
android:launchMode=”singleTop”
启动活动时,如果发现返回栈的栈顶已经是该活动,则直接使用它,不会再创建新的活动实例
如果活动不是在栈顶,则会再创建新的活动实例
示意图:
3、singleTask
每次启动该活动时系统首先检查返回栈中是否存在该活动的实例,如果发现已经存在则直接使用该实例,并把这个活动智商的所有活动统统出栈,如果没有发现则重新创建一个实例
保证每次只有一个实例
示意图:
4、singleInstance
活动会启用一个新的返回栈来管理这个活动
使不同的程序共享一个活动实例成为可能
示意图:
6、活动的最佳实践
技巧也很重要
1、知晓当前在哪一个活动
在AppCompatActivity和具体Activity之间加一个普通java类,使其打印当前实例类名
实现如下:
创建BaseActivity继承AppCompatActivity
修改具体Activity的继承结构,不再继承自AppCompatActivity,改为继承自BaseActivity
覆写BaseActivity的onCreate()方法:
加入一行Log.d(“BaseActivity”, getClass().getSimpleName());
2、随时随地退出程序
新建一个ActivityCollector类作为活动管理类
通过静态List管理活动,有三个方法:静态添加活动类、静态删除活动类、静态销毁所有活动类
在BaseActivity的onCreate()方法中使用ActivitCollector.add(this);
在BaseActivity的onDestroy()方法中使用ActivitCollector.remove(this);
在任何想直接退出的地方加一个按钮,在按钮的OnClick方法中加入:
ActivityCollector.finishAll();
Ps:android.os.Process.killProcess(android.os.Process.myPid());杀死当前进程,该方法只能杀死当前进程,不能杀掉其他进程
3、启动活动的最佳写法
在要被启动的活动中加入一个方法:
public static void actionStart(Context context, String data1,String data 2) {
Intent intent = new Intent(context, SecondActivity.class);
intent.putExtra(“param1”, data1);
intent.putExtra(“param2”,data2);
context.startActivity(intent);
}
需要多少启动参数,就加入多少启动参数,然后在启动活动中直接一行启动就行
SecondActivity.actionStart(FirstActivity.this, “data1”, “data2”);
这个方法可以作为代码编写规范使用