文章适合新手了解Android的Activity与intent。文章在编写过程中难免有疏漏和错误,欢迎大佬指出文章的不足之处;更多内容请点进👉 Lino_White 👈查看。
未来的世界充满着各式各样的数据,我们该怎么好好利用起来呢?开启正文吧~~~
如有侵权请告知,更多Android学习笔记在👉 Lino_White的Android学习笔记 👈
一、活动(Activity)与intent
1.1 活动(activity)是什么?
Activity活动存在于android中,是所有程序的根本,流程都运行在Activity之中,Activity是Android当中最基本的模块之一。主要用于和用户进行交互。
1.2 intent在活动之间穿梭
intent为不同组件之间通信的“媒介”专门提供组件互相调用的相关信息。一般可被用于启动活动、启动服务以及发送广播等场景。
大致可以把intent分为两种:显示intent和隐式intent。
1.2.1 显示intent
Intent有多个构造函数的重载,其中一个是intent(context packagecontext, class<?>cls)。
这个构造函数接收两个参数,第一个参数context:要求提供一个启动活动的上下文;第二个参数class:想启动的目标活动。
Activity类提供了一个**startactivity()**方法来给我们使用intent,这个方法是专门用于启动活动的,其接收一个intent参数。
语法:
Intent intent=new Intent(MainActivity.this,想调用其他活动的.class);
startActivity(intent);
像这种“意图”非常明显想去到哪个活动的方式称之为显示intent。
1.2.2 隐式intent
相比于显示intent,隐式则不明显,它并不明确指出我们想要启动哪个活动,而是指定了一系列更为抽象的action和category等信息,然后交由系统去分析这个intent,并帮我们找出合适的活动去启动。
合适的活动简单来说就是可以响应我们这个隐式intent的活动。
实例:
androidmanifest.xml文件在要跳转的活动编写
<intent-filter>
<action android:name="android.intent.action.jizhenghuod" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
Mainactivity文件
Intent intent=new Intent("android.intent.action.jizhenghuod");
startActivity(intent);
Action指明当前活动可以响应对应的name,category则包含一些附加信息,更精确地指明了当前的活动能够响应的intent还可能带有category。
每个intent只能指定一个action,但却能指定多个category。
1.2.3 隐式intent更多用法
隐式intent不仅可以启动自己程序内的活动,还可以启动其他程序的活动,这使的android多个应用程序之间的功能共享成为可能。
Intent当中有一个方法setData( ),接收URI对象,主要用于指定当前的intent正在操作的数据,这些数据通常都是以字符串的形式传入到uri.parse( )方法中解析产生的。
实例(调用系统浏览器):
Intent intent=new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.vkxx.top"));
startActivity(intent);
首先指定了intent的action为Intent.ACTION_VIEW,是一个android系统内置的动作,其常量值为android.intent.action.VIEW。
与此对应,我们可以在androidmanifest.xml中的< intent-filter>中配置一个< data>,用于更精确地指定当前活动能够响应什么类型的数据。
< data>主要可以配置以下内容:
android:scheme:用于指定数据的协议部分,如实例的http。
android:host:用于指定数据的主机名部分,如实例的www.vkxx.top。
android:port:用于指定数据的端口部分,紧随在主机名后;如实例的80。
android:path:用于指定主机名和端口之后的部分,如一段网址中跟在域名之后的内容,如实例的www.vkxx.top/post.1。
android:mimeType:用于指定可以处理的数据类型,允许使用通配符的方式进行指定。
只有< data>中指定的内容和intent中携带的data完全一样时,当前活动才能够响应该intent;不过一般在< data>中都可以指定过多的内容。
刚才我们的实例只需要指定android:scheme为http,就可以响应所有的http协议的intent。
除了http协议外,也可以指定其他协议,比如geo表示显示地理位置,tel表示拨打电话。
实例(调用系统电话):
Intent intent=new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:1008611"));
startActivity(intent);
其中,Intent.ACTION_CALL是一个android系统的内置动作,data部分指定链协议是tel。
1.3 intent传递数据给下一个活动
Intent除了可以启动活动外,还可以在启动活动时传递数据给下一个活动。
Intent为传递数据提供了一系列putExtra()方法的重载,可以将传递的数据暂存在intent中,启动下一个活动后,把这些数据从intent中取出即可。
实例:
在第一个活动的按钮点击事件中添加代码:
String data="实现数据传输";
Intent intent=new Intent(MainActivity.this,Main2Activity.class);
intent.putExtra("语句",data);
startActivity(intent);
//使用putExtra()方法传递一个字符串,
// putExtra()方法接收两个参数,第一个参数是键,用于从intent中取值;
// 第二个参数是键值,为真正传递的数据。
在下一个活动中取出传递的数据:
Intent intent=getIntent();
String data=intent.getStringExtra("语句");
Log.d("活动接收到数据:",data);
// getIntent()方法获取用于启动当前活动的intent,
// 调用getStringExtra()方法获取传递字符串的数据。
// 整型数据则用getIntExtra()方法,以此类推。
1.4 intent返回数据给上一个活动
Intent可以传递数据当然也可以返回数据。不同的是,返回到上一个活动只需要按一下手机的back键就可以,并没有一个用于启动活动intent来传递数据。
Activity(活动)中有一个** startActivityForRester() **方法也是用于启动活动的,这个方法会在活动销毁时返回一个结果给上一个活动,这个方法是最好用于返回。
实例:
在第一个活动按钮的点击事件添加代码:
Intent intent=new Intent(MainActivity.this,Main2Activity.class);
startActivityForResult(intent,1);
// 用startActivityForResult()方法启动第二个活动,
// 请求码只要是一个唯一值即可,这里传入1。
在第二个活动按钮的点击事件(返回数据)添加代码:
Intent intent=new Intent();
intent.putExtra("返回语句","返回的数据成功");
setResult(RESULT_OK,intent);
finish();
// 创建了intent,用于传递数据,没有指定任何活动。
// 将传递的数据存放在intent中,调用setResult()方法,专门用于返回数据给上一个活动。
// setResult()方法接收两个参数,第一个参数用于向上一个活动返回处理结果
// (一般只使用RESULT_OK或RESULT_CANCELED两个值);
//
// 第二个参数则把带有数据的intent传递回去,
// 调用finish()方法销毁当前活动。
当返回上一个活动时,当前活动被销毁后会调用上一个活动的onActivityResult()方法,需要在上一个活动中重写方法得到返回的数据。
@Override
protected void onActivityResult(int requestCode1, int resultCode5, Intent data) {
switch (requestCode1){
case 1:
if (resultCode5==RESULT_OK){
String redata=data.getStringExtra("返回语句");
Log.d("第一个活动得到数据:",redata);
}
break;
default:
}
// onActivityResult()方法有三个参数,第一个参数requestCode1,即在启动活动时传入的请求码(1)。
// 第二个参数resultCode5,即在返回数据时传入的处理结果(RESULT_OK)。
// 第三个参数data,即携带着返回数据的intent。
// 在一个活动中可能调用startActivityForResult()方法启动不同的活动,
// 每个活动返回的数据都会回调到onActivityResult()方法中,
// 所以在onActivityResult()方法中要检查requestCode1的值来判断数据来源。
在第二个活动如果用户表示通过点击按钮返回到上一个活动,而是通过按下手机的back键,数据是没有办法传输的,需要我们在第二个活动中重写onBackPressed()方法来解决:
@Override
public void onBackPressed() {
Intent intent=new Intent();
intent.putExtra("返回语句","back键数据返回");
setResult(RESULT_OK,intent);
finish();
}
1.5 活动(activity)的生命周期
一个APP,会有很多的活动,活动之间经常要进行切换,数据的交互等,这时候就需要用到生命周期这块的知识。只要抓握了活动的生命周期,才能更流畅的写APP程序出来。
1.5.1 返回栈
Android中的活动是可以层叠的。每启动一个新的活动,就会覆盖在原活动之上, 点击手机back键会销毁最上面的活动,前一个活动就会重新显示出来。
其实android是使用任务(Task)来管理活动的。一个任务就是一组存放在栈里的活动的集合,这个栈也被称作返回栈(back stack)。
栈是一种后进先出的数据结构,在默认情况下,每当启动了一个新的活动,会在返回栈中入栈,并处于栈顶的活动会出栈,这是前一个入栈的活动就会重新处于栈顶的位置。
系统总是会显示处于栈顶的活动给用户。
如图所示,返回栈是如何管理活动入栈出栈操作的。
1.5.2 活动状态(四种:运行、暂停、停止、销毁状态)
每个活动在生命周期中最多可能会有4种状态。
- 运行状态
当一个活动位于返回栈的栈顶时,这是活动就处于运行状态。系统最不愿意回收就是处于运行状态的活动,因为这会带来非常差的用户体验。
- 暂停状态
当一个活动不再处于栈顶位置,但仍然可见时,说明活动进入暂停状态。
活动不再栈顶,但还是处于可见,这是因为不是每一个活动都会占满整个屏幕的。如:对话框的活动只会占用屏幕中间的部分区域。
处于暂停状态的活动仍然是完全活着的,系统不愿意去回收这种活动(因为它是可见的,回收可见的活动会在用户体验方面有不好的影响),只要在内存极低的情况下,系统才会去考虑回收这种活动。
- 停止状态
当活动不再处于栈顶位置,并且完全不可见时,就进入停止状态。
系统仍然会为活动保存相应的状态和成员变量,但这不是完全可靠的,当其他地方相应内存时,处于停止状态的活动有可能会被系统回收。
- 销毁状态
当活动从返回栈中移除后就变成了销毁状态,系统会最倾向于回收处于这种状态的活动,从而保证设计的内存充足。
1.5.3 活动的生存期
Activity类中定义了7个回调方法,覆盖了活动生命周期的每一个环节。
onCreate():此方法会在活动第一次被创建的时候被调用,要在方法中完成活动的初始化操作,比如:加载布局、绑定事件等。
onStart():此方法在活动由不可见变为可见时调用。
onResume():此方法在活动准备好和用户进行交互的时候调用。此时的活动一定位于返回栈的栈顶,并且处于运行状态。
onPause():此方法在系统准备去启动或者恢复另一个活动时调用。通常会在方法中将一些消耗CPU的资源释放掉,以及保存一些关键数据,但这个方法的执行速度一定要快,不然会影响到新的栈顶活动的使用。
onStop():此方法在活动完全不可见时调用。跟onPause()方法的主要区别在于:启动的新活动时一个对话框式的活动,那么onPause()方法会得到执行,onStop()方法并不会执行。
onDestory():此方法在活动被销毁之前调用,之后活动的状态将变为销毁状态。
onRestart():此方法在活动由停止状态变为运行状态之前调用,也就是活动被重启动了。
7个方法中处理onRestart()方法,其他都是两两相对的,从而又可以将活动分为3种生存期。
完整生存期:活动在onCreate()方法和onDestroy()方法之间所经历的,就是完整生存期。一般情况,一个活动会在onCreate()方法中完成各种初始化操作,而在onDestroy()方法中完成是否内存的操作。
可见生存期:活动在onStart()方法和onStop()方法之间所尽力的,就是可见生存期。
活动对于用户总是可见的即便有可能无法和用户进行交互。通过两个方法,合理管理那些对用户可见的资源。
比如在onStart方法中对资源进行加载,而在onStop方法中对资源释放,从而保证处于停止状态的活动不会占用过多的内存。
前台生存期:活动在onResume()方法和onPause()方法之间所经历的就是前台生存期。
在前台生存期内,活动总是处于运行状态的,此时活动时可以和用户间交互的,平时看到和接触最多的就是这个状态下的活动。
1.5.4 实例活动的生命声明周期
略,可调用7个活动进行log日志查看他们的活动。
1.6 活动的启动模式
在实际项目中应该根据特定的需求为每个互动指定恰当的启动模式。
活动的启动模式一共有4种,分别为:standard、singleTop、singleTask和singleInstance。
可以在androidmainfest.xml文件中通过给标签指定android:launchMode属性来选择启动模式。
1.6.1 standard
Standard是活动默认的启动模式,在不进行显式指定的情况下,所有活动都会自动使用standard启动模式。
在standard模式(即默认情况)下,每当启动一个新的活动,它就会在返回栈中入栈,并处于栈顶的位置。
对于使用standard模式的活动,系统不会在乎活动是否已经在返回栈中村子,每次启动都会创建该活动的一个新的实例。
1.6.2 singleTop
当活动的启动模式指定为singleTop,在启动活动时如果发现返回栈的栈顶已经是该活动,则认为可以直接使用它,不会再创建新的活动实例。
使用singleTop模式可以很好解决重复创建栈顶活动的问题。
1.6.3 singleTask
当活动的启动模式指定为singleTask,每次启动该活动时系统首先会在返回栈中检查是否存在该活动的实例,如果发现已经存在则直接使用该实例,并把在这个活动之上的所有活动统统出栈,如果没有发现就会创建一个新的活动实例。
1.6.4 singleInstance
此模式是4种启动模式中最特殊也最复杂的一个,指定为singleInstance模式的互动会启用一个新的返回栈来管理活动(singleTask模式指定不同的taskAffinity,也会启动一个新的返回栈)。
这种模式下会有一个单独的返回栈来管理活动,不管是哪个应用程序来访问活动,都共用的同一个返回栈,解决共享活动实例的问题。
1.7 活动的最佳实践
知识点少,但是运用的技巧却许许多多,下面介绍一下几种实践技巧。
1.7.1 知道当前的活动是哪个?
Log.d(“当前活动:”,getClass().getSimpleName());
1.7.2 退出程序
想随时随地退出程序和所有的进程,可以做一个注销或者退出功能。
新建一个java文件:APPout类作为活动管理器:
public class APPout {
//创建List来暂存活动。
public static List<Activity> activities=new ArrayList<>();
//创建addActivity()方法用于在list里添加活动
public static void addActivity(Activity activity){
activities.add(activity);
}
//创建delectActivity()方法用于在list里移除活动
public static void delectAcitity(Activity activity){
activities.remove(activity);
}
//创建outActivityAll()方法用于将list中存储的活动全部销毁掉
public static void outActivityAll(){
for (Activity activity:activities){
if (!activity.isFinishing()){
activity.finish();
}
}
}
在MainActivity中的onCreate方法中添加:
APPout.addActivity(this);
//在onCreate方法中调用Appout类中的addActivity方法,
//表示将当期正在创建的活动添加到活动管理器里
在MainActivity中新创建onDestroy()方法:
@Override
protected void onDestroy() {
super.onDestroy();
APPout.delectAcitity(this);
}
//在onDestroy方法中调用Appout类中的delectAcitity方法
//表明将一个马上要销毁的活动从活动管理器里移除
做完之后,想在哪个活动直接退出程序,可以直接调用Appout类中的outActivityAll()方法即可。
APPout.outActivityAll();
为了保证程序完全退出,可以写一个杀掉进程的代码:
android.os.Process.killProcess(android.os.Process.myPid());
//killProcess()方法用于杀掉一根进程,接收一个进程id参数;
//通过myPid()方法获取当前程序的进程id;
//注意:killProcess()方法只能用于杀掉当前程序的进程,不能使用方法来杀掉其他程序
好了,Android第一章Activity与Intent就到这里结束了。
不定时更新,催更的话请私信或留言下方给小编哟!一催更就更新的Lino_white博主。