Activity
1.何为活动?
Activity 活动:Android四大组件之一,它是一种包含用户界面的组件,主要用于和用户进行交互。通俗化理解为提供可视化界面,和电脑系统的可视化界面差不多。
也就是我们在App中的可视化界面部分,在活动内部承载了许多控件,例如按钮,文本框等等。
一般来说,在一个Andorid程序中,可以包含零或多个活动,但是几乎没有哪个Android程序是不包含活动的,除非你不想看见它
2.活动的生命周期
我们在使用Android App的时候是否有过以下体验:
- 打开App出现一个页面
- 点击页面内按钮跳转到新页面
- 点击返回返回到上一个页面
- 点击返回无法返回到上一页面再点一次程序关闭
实际上这些操作内就包含了活动的各个生命周期以及活动状态,接下来我们对活动的生命周期做一个分析。当我们掌握了Android的生命周期后,就可以写出更流畅和资源使用更合理的程序。
2.1活动管理:返回栈
在使用App的时候,我们会发现界面是一层一层的,点一下返回,界面就会回到上一层,或者直接回到主页面。在Android中是用任务来管理活动的,任务就是一个存放在栈中的活动的集合。这个栈的名称叫返回栈。
顾名思义,一个以栈为基础的任务,它的运行机制就是出栈入栈。
当我们启动一个活动的时候
这个活动就压到栈里并且处于栈顶的位置
然后当我们再次产生新的活动的时候,新入的活动入栈,也处于栈顶位置
始终是显示栈顶的活动
当我们点击Back或者直接在程序跳转活动的时候销毁活动,那么处于栈顶的活动就会出栈,新开启的活动重新进入栈顶,程序显示给我们的可视界面总是栈顶的那个活动。也就是图中的尾巴根儿
2.2活动状态
活动具有四个状态:
- 运行状态:该状态就是活动处于栈顶的状态,用户可视的界面都是运行状态,在这个状态下,最好不要轻易的销毁这个页面,谁也不想用着用着页面突然没了吧.(狗头.jpg)
- 暂停状态: 处于活动的暂停状态不处于栈顶,但仍然可见。在这种状态下的活动是暂停的。有一些不会占满屏幕的活动,例如一个活动形式的对话框或者一个活动形式的弹出页面。两个活动同时处于视图中,这时候这个活动就处于暂停状态。
- 停止状态: 这个活动对应的就是被压入栈不处于栈顶位置的活动,除了暂停状态下的特殊状态的活动。
- 销毁状态: 销毁状态就是处于出栈的活动,gameover
2.3活动的生命周期
活动的生命周期分为七个环节:
- onCreate() 创建活动阶段
- onStart() 启动活动阶段
- onResume()交互阶段
- onPause()暂停阶段
- onStop()停止阶段
- onDestroy()销毁阶段
- onRestart()重新启动阶段
可以用游戏地下城与勇士来举个小例子来理解这几个阶段:
1.onCreate()
2.onStart()
3.onReaume()
4.onStop()
此时处于列表中的其他角色.jpg
5.onDestroy()
6.onRestart()
登录列中中的其他角色.gif(滑稽)
相信到这里很多人就理解活动的七个环节了。如果还有疑问可以看这个
3.如何使用活动
3.1创建一个活动
创建活动很简单,我们只需要在项目名称处右键找到它
或者根据需求选择红框下方的选项即可。在这里我们创建一个EmptyActivity为他命名为NormalActivity,让我们来看看都生成了那些文件
1.这个文件用来完成我们想实现的逻辑部分,也就是各种功能的逻辑实现环节。
2.这里用来实现视图。
安卓的一个独特之处就在于将视图和逻辑分开。
关系就类似于…这样吧…
当然我们不要忘记了这里还有NormalActivity的身影
在AndoridMainfest.xml文件中可以找到它
<activity android:name=".NormalActivity" />
<activity android:name=".MainActivity">
它就是在这里被注册的,只有它被注册了,这个司机才允许上路
3.2 Layout解析
在Layout下,我们目前知道这些区域便可以很好的完成一些简单的任务
左上角为控件区,提供了丰富的控件来实现我们想实现的功能,可以直接以拖拽的形势将控件拖入到可视化界面内,左下角就会生成一个目录来表明目前的逻辑结构。右上角的部分用于切换代码显示Layout、或者显示可视化界面或者两者都显示。使我们的开发更直观便捷。
我们可以来看一下布局的代码对代码进行分析:
<?xml version="1.0" encoding="utf-8"?> //版本 编码方式
<androidx.constraintlayout.widget.ConstraintLayout //代表了最外围的主要布局是什么,这里面是constarintlayout布局
xmlns:android="http://schemas.android.com/apk/res/android" //目前先不解释,以后用到在解释
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" //表示控件宽度和父元素一样宽,也就是布满横向的像素
android:layout_height="match_parent" //同上
tools:context=".NormalActivity"> //场景为 NormalActivity
</androidx.constraintlayout.widget.ConstraintLayout>
如果我们添加一个控件,例如按钮:就会在主控件的内部多出这么几行代码:
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
这个意思就是我么你生成了一个按钮,他的长和宽都是当前元素只要能够刚好包含在内即可,就是按照内容长度自动设置。这就是wrap_content
的作用。界面内它是这样的:
是不是感觉很秀 仅需要几行代码就可以定义出一个按钮来,当然我们不仅可以进行拖拽还可以自己手写代码来进行定义。可以为其添加很多属性,例如横纵向,名称,和谁对齐等等,在这里就不一一列举了,等以后研究控件的时候回专门去写一遍文章出来。在这里定义按钮也是为了后面的跳转页面做准备。
3.3活动的运行效果:
让我们试着运行一下看看这个活动是怎么样的呢?
在前面的文章我已经做过从安装到运行的教程了一些简单的步骤就不详细介绍了有兴趣的可以看:
Android(AndroidStudio&Kotlin)安装到运行过程及常见问题汇总
我们发现它成功的运行了!并且显示出了这个按钮! 这是好的迹象,我们可以利用这个按钮做更多的事情!
4.活动之间如何进行跳转
4.1Toast
在这里我们就可以去做一些日常app中的点击行为跳转界面的操作了.在这之前我要介绍一个非常好的提醒方式,用于你测试你的跳转是否是正确的。它就是Toast
让我们把视角转到NormalActivity.class上来
首先我们需要给把控件通过代码让class和xml两兄弟联起手来,要不然谁也不知道谁,两眼一抹黑。
这时候就需要去声明控件,并且要给他绑定一个点击事件的监听器,这样可以让我们在按这个按钮的时候可以去做一些其他的事情。我们在onCrate内书写以下代码:
Button button1=(Button)findViewById(R.id.olaola);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
其中 findViewById的意思就是指从视图中找到ID为括号内的控件进行绑定。R.id.olaola中olaola就是我给按钮起的名字,在Layout文件中是这样显示的。
android:id="@+id/olaola"
当我们绑定成功后,就可以为它设置监听事件,这个就是说我们通过什么样的操作就能够触发监听事件内的什么操作,这个onClickListener
就是点击事件触发。当我们点击的时候,执行onClick
内部的代码。
当然按钮按过还是没按过这个不好判断,我们就需要用到Toast这个提醒方式。它是这样来书写的:
Toast.makeText(NormalActivity.this,"你按了这个按钮",Toast.LENGTH_LONG).show();
第一个参数是所在的Activity,第二个参数为显示内容,第三个为对应显示时间,Toast.LENGTH_LONG显示时长为3.5S,SHORT为2S。我们将代码写到点击事件内。运行来看看
当我们点击按钮后,下方出现了如下提示,这时候就代表我们已经出发了点击事件!
4.2 界面之间跳转的两种方式:显式Intent与隐式Intent
神来之笔的按钮点击事件完毕之后,需要将它真正的价值体现出来,点击跳转页面。这时候问题来了,跳转页面有需要那些必要的东西呢?
这里隆重推出Intent翻译过来就是意向。
Intent是Android程序中各个组件进行交互的一种重要方式,不仅可以指明组件想要执行的动作,也能用来传递数据。Intent一般用于启动活动,启动服务以及发送广播等场景。
也就是说,Intent实际上就相当于两个国家之间的信使,有啥事它给个信就可以继续推动。根本不用放狼烟。只不过这个比信使快多了。
大致上,Intent分为两种:显式Intent和隐式Intent
4.2.1显式Intent
显式Intent是这样使用的:
Intent intent=new Intent(FirstActivity.this,SecondActivity.clss);
StartActivity(intent);
Intent的这个构造函数接受两个参数,第一个是Context提供一个启动活动的上下文,也就是本活动的环境,一般都是叫该页的名字.this,第二个参数是目标活动,我们将想要跳转的页面的名字填入其中。这样意图就很明显了。
第二行通过StartActivity启动目标活动,达成跳转页面的目的。
我们来简单的实现一下:
public void onClick(View v) {
Toast.makeText(NormalActivity.this,"你按了这个按钮",Toast.LENGTH_LONG).show();
Intent intent=new Intent(NormalActivity.this,DialogActivity.class);
startActivity(intent);
}
在这里我把目标活动设为Dialog主题的页面,便于区分,下面去运行它:
点击后成功的跳转了!
4.2.2隐式Intent
隐式Intent传递的更加含蓄,它使用action
和category
来判断是否要跳转到那个界面,它并不明确的之初我要跳转的界面是哪个。隐式的Intent传递能够把诸多的传递统一起来,不至于让我们到开发后期面对好几百个Intent跳的乱七八糟的窘境。
它需要我们在被跳转的Mainfest内定义action和category
代码如下:
<activity android:name=".DialogActivity"
android:theme="@style/Theme.AppCompat.Dialog">
<intent-filter>
<action android:name="com.example.jabaproject.ACTION_START"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
这样定义好后,我们就可以在NormalActivity中指定action和category,当两者一一匹配后,就可以进行隐式的Intent跳转活动了。
在NormalActivity中的点击事件内是这样定义的
Intent intent=new Intent("com.example.javaproject.ACTION_START");
为什么说一一对应却没有去定义category呢?这是因为在DialogActivity的xml中将其设置为DEFAULT的默认category了,如果我们想增加category的对应关系,可以分别在xml和NormalActivity中增加以下和修改以下代码:
NormalActivity:
intent.addCategory("com.example.javaproject.MY_CATEGORY");
Mainfest.xml
<category android:name="com.example.javaproject.MY_CATEGORY"/>
这样添加后,action和category就可以一一对应进行跳转了,感兴趣的朋友可以亲手试试看!
需要注意的是:这里每个Intent只能定义一个Action,但是却可以指定多个category
5.活动之间如何进行通信
活动之间数据的传递也是通过Intent来实现的,可以分为两个部分
5.1向下一个活动传递数据
在Intent中,通过putExtra()
方法来传输数据
如果你想将一个数据传到下一个活动中,那么你可以这么写:
String str1="我成功的过来啦!";
Intent intent=new Intent(MainActivity.this,NormalActivity.class);
intent.putExtra("extra_data",str1);
startActivity(intent);
这样就可以将字符串的内容通过Intent启动传入到下一个活动中了。
那么我们如何在下一个活动中接收到这个活动呢?
我们先在下一个活动中定义一个文本框来显示这个字符串,相信看了前面,定义控件对于你来说并不困难。
NormalActivity:
Intent intent=getIntent();
String data=intent.getStringExtra("extra_data");
TextView textView=findViewById(R.id.textView);
textView.setText(data);
在这里我们调用了getStringExtra方法,将传入活动时约定好的“extra_data”为接头暗号,如果答对了暗号,就接收它的数据并且显示到textview控件上。让我们运行一下看看结果吧
可以看到TextView成功的讲数据传输过来了!这一步对于我们来说非常重要,因为当我们真正开发一个程序的时候,很多时候都需要把数据在各个页面之间传输,类似购物商城的app,你的购物车数据就要在很多界面都有显示,这时候就是它大显身手的地方了,当然还有一些其他的方法。以后我们共同学习!
5.2将数据返回到上一个活动
找到一个很不错的文章讲述了如何把数据返回到上一个活动大家可以参考一下:
点击跳转转自:Android_小牧
也可以看我的写的示例:
让我们用5.1和5.2结合起来,让数据既能够传过去也能穿回来。
首先是第一个活动,MainActivity,定义一个按钮,绑定控件并添加一个监听器监听点击事件。
Button button=findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String data="传过去";
Intent intent=new Intent(MainActivity.this,Main2Activity.class);
intent.putExtra("extra",data);
startActivityForResult(intent,1);
需要注意的是,启动活动由startActivity()
变成了 startActivityForResult()
,这样做的目的是,发送一个类似于身份牌的参数,让接受的活动可以根据这个身份牌来识别是从哪里来的,我们之后可以将数据按照这个门牌号在送回去,接下来是Main2Activity中接受数据的代码。
代码如下:
final Intent intent=getIntent();
String extra=intent.getStringExtra("extra");
Toast.makeText(Main2Activity.this,extra,Toast.LENGTH_LONG).show();
通过getIntent()
来获取Intent信息,通过getStringExtra()
方法来识别我们在传输时加入的数据,匹配口令成功就能获得这个数据,在通过Toast来显示数据。
那么接下来该如何返回数据呢?
首先我们要知道的是,返回上一个活动可以有以下两种方式,第一种方式就是点击按钮或者一系列控件;第二种是按BACK键直接返回上一个活动。这时候我们就要根据情况来写代码:
1.按BACK键返回,我们需要重写onBackPressed()
来传回数据。
Intent intent1=new Intent();
intent1.putExtra("data_return","i am back!!!");
setResult(RESULT_OK,intent1);
finish();
在这里通过putExtra()
加入想要传回的口令和数据, 然后我们通过setResult()
方法来传回一个resultcode,这样返回活动接收到这个code就晓得从哪里来了。
2.按按钮返回
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent1=new Intent();
intent1.putExtra("data_return","i am back");
setResult(RESULT_OK,intent1);
finish();
这里我们不适用Inetnt做跳转,单纯的用于传输数据,活动的销毁则使用finish()
来完成。最后返回code和和data。
接下来就是在MainActivity中重写onActivityResult方法来匹配resultcode并显示回传的参数
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
switch (requestCode) {
case 1:
if (resultCode == RESULT_OK) {
returnedData = data.getStringExtra("data_return");
Log.d("**********返回数据为**********", returnedData);
}
break;
default:
}
}
这个方法有三个参数,第一个参数为requsetCode,是需要回传数据的活动发送的,第二个参数和第三个参数是resultCode和data,是回传数据的活动传回来的,然后我们重写这个方法,根据返回的requsetCode和resultCode匹配是否是需要返回的数据,如果是则可以抽取这个数据进行使用。
如果理解起来比较抽象,可以想象以下例子:
某大型地下组织MainActivity企图用现金购买一批货物,然后他就给了小弟Intent一封信,让他转交给供货方Main2Activity,这封信上是这么写的:
《见字如见人,我就是MainActivity,快来把我想要的给我》
然后Main2Activity收到之后,说,可以,继续交易。但是我要把我的货物加个密,毕竟送出去了这个小弟不知道半路就让谁截胡了呢。于是他定下了一个暗号 “data_return”,答对暗号的才可以拿走货。
这时候Intent小弟就逛了一圈找到了自己的老大,老大一看,嘿 我知道暗号“data_return” 可以拿货了!
这时候第三个参数data保险箱就被打开了,这个货物就可以让我们为所欲为了=。=返回显示在空间上也好,直接打印日志也好。
但如果,如果这个小弟走错了路,或者老大记错了暗号,requestcode
和resultCode
对不上,那么对不起
6.常见问题(大家有什么问题可以提出来一起分享)
6.1Android 四大组件
- Android四大组件概解转自:二十岁了还没去过星巴克。该文章内简述了Android的四大组件。
6.2通过代码理解活动的生命周期
6.3深入理解Context到底是个啥?
-理解Context转自:兮与谁歌
6.4Toast的几种使用方式
Toast使用简单小结转自:残风乱了温柔