这是一篇关于android四大组件之一的活动的笔记整理。ps:作者是android初学者,文中如有说的不对之处欢迎指出
活动的创建
在你的包名处右键–New–Activity
创建活动的时候可以选择勾选
Generate Layout File 生成一个布局文件
Launcher Activity 把这个活动作为启动时候第一个活动
活动的生命周期
声明:图片源自网络
android中活动的生命周期可以分为全生命周期,可视生命周期,活动生命周期。
全生命周期:从活动的创建到销毁。从onCreate到onDestroy
可视生命周期:活动在界面上从可见状态到不可见状态。从onStart到onStop。包括活动完全显示在界面上,还是仅有部分显示在用户界面上而不能和用户交互。
活动生命周期(前台生命周期):活动处于运行状态,这时候的活动可以和用户交互。onResume到onPause
活动生命周期的七个方法,分别在活动进入不同的状态时候调用。现在通过重写这七个方法,在里面加入调试信息,来观察这些方法调用的时机,来学习活动的生命周期。
在主活动中重写这这个方法,按ctrl+O可以快速重写。
public class MainActivity extends AppCompatActivity {
public static final String Tag = "MainActivity";
private Button btn_display,btn_implict;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(Tag,"is onCreate");
init();
onClick();
}
public void init(){
btn_display = (Button)findViewById(R.id.btn_display_intent);
btn_implict = (Button)findViewById(R.id.btn_implict_intent);
}
public void onClick(){
btn_display.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,Display_intent.class);
startActivity(intent);
}
});
}
@Override
protected void onStart() {
super.onStart();
Log.d(Tag,"is onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.d(Tag,"is onResume");
}
@Override
protected void onPause() {
super.onPause();
Log.d(Tag,"is onPause");
}
@Override
protected void onStop() {
super.onStop();
Log.d(Tag,"is onStop");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(Tag,"is onRestart");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(Tag,"is onDestroy");
}
}
创建一个活动,在其布局界面加入两个按钮。
按钮1,用于显示切换活动,按钮2,用于隐式切换活动。此处不具体说明切换活动,见下面活动切换,这里先通过其来观察活动的生命周期方法的调用。
注册按钮1的监听事件btn_display.setOnClickListener。在里面切换到另一个活动。
下面是主活动的布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.asus.study_activity.MainActivity">
<Button
android:id="@+id/btn_display_intent"
android:text="显示切换活动"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/btn_implict_intent"
android:text="隐式切换活动"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
配置文件AndroidManifest.xml文件中
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".Display_intent"></activity>
</application>
其中
<activity android:name=".Display_intent"></activity>
确保你需要切换的活动在配置文件中注册。
在主活动的注册中,有四行代码
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
这是说明这个活动是该应用程序启动时候第一个启动的活动。
好了,回到正题,学习活动的生命周期。
***1.当运行程序时候,在下面的日志中可以看到
当活动第一次被创建的时候,会执行onCreate,onStart,onResume
其中,onCreate是创建活动并进行一些初始化,比如按钮监听事件注册,列表适配器初始化等等
onStart方法,是活动从不可见变为可见的时候调用
onResume,这是活动准备好和用户进行交互的时候调回用的,说明这个活动已经处于栈顶正在运行状态。
***2.这时候,我们点击一下按钮进行切换活动。观察日志,出现
第二个活动,并没有任何东西
onPause方法,一般是在系统准备启动其他的活动的时候调用的
onStop方法,是在该活动完全不可见的时候调用的,在里面一般释放掉一些占用内存的资源。
当按下按钮进入第二个活动的时候,主活动处于完全不可见状态,因此先调用onPause方法,然后调用onStop方法。
***3.这时候,我们按下模拟器中的回退键BACK,观察日志中显示
可以看到,主活动调用了onRestart,onStart,onResume。活动从不可见状态恢复到能够和用户交互的状态。
活动从停止状态被唤醒,会依次调用onRestart,onStart,onResume。
onRestart:活动由停止状态变为运行状态调用
onStart:活动由不可视变为可视
onResume:活动能够和用户进行交互
***4.现在,我们在主界面的状态下,按下回退键BACK退出到模拟器的主界面,观察日志
可以看到,活动从可视状态到完全不可视并且销毁,所以执行了onPause方法,onStop方法,onDestroy方法。
活动切换
单一的一个活动,往往不能满足我们的需要,一个应用程序往往是有很多个活动的,那么如何从一个活动切换到另一个活动呢?
显示切换
活动切换,分为显示切换和隐式切换两种。其中,显示切换就是具体指定要切换的活动是哪一个活动。
现在我们来看一下刚刚在按钮1注册监听事件里面的活动切换。
Intent intent = new Intent(MainActivity.this,Display_intent.class);
startActivity(intent);
这是最简单显示切换,第一行代码,创建了一个Intent类的对象intent。Intent ”意图“,可以用来切换活动,开启服务,发送广播等等。它的其中一个构造函数接收两个参数,第一个是上下文,要求提供启动活动的上下文,第二个参数是Class,要求提供想要提供的目标活动。
有了这个意图之后,就可以使用android中提供的startActivity方法,这个方法就是用来启动活动的方法。
隐式切换
隐式启动活动,就是不指定具体启动的活动,让系统通过一些标志来判断要启动的活动是哪一个活动。
现在在public void onClick()函数中加入第二个按钮的注册监听事件。
btn_implict.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("com.example.asus.study_activity.START");
intent.addCategory("android.intent.category.CATEGORY");
startActivity(intent);
}
});
并且在配置文件中AndroidManifest.xml。修改如下代码
<activity android:name=".Display_intent">
<intent-filter>
<action android:name="com.example.asus.study_activity.START"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.CATEGORY"/>
</intent-filter>
</activity>
这个时候重新构建一下,点击下面的按钮2隐式切换活动。会发现还是成功的进入到了前面的Display_intent活动中。
在隐式切换活动中,通过设置action以及category,系统将会自主去匹配符合条件的活动并且进行切换。需要注意的是,一个活动只能有一个action,但是可以有很多个category。而且,在配置category的时候,必须要加入其中一个category即默认
`<category android:name="android.intent.category.DEFAULT"/>`
否则程序会因为没有正确匹配category而崩溃闪退。
在按钮2的点击监听事件方法中,使用了另一个Intent的构造函数,这个构造函数的参数是action name,直接传入我们在配置文件中所定义的action name即可。或者,你也可以调用intent的setAction方法,来设置action。
其次,调用了intent的addCategory方法,给这个意图再加上一个category,这里面传入一个参数,为我们刚刚在配置文件中第二个category。
这里你可以会注意到,第一行category android.intent.category.DEFAULT并没有使用addCategory方法加入,这是因为这个category是默认的,你必须要在配置文件中使用,但是在intent中不用加入它。
现在,我们把这个intent放入startActivity方法中,就可以成功的开启符合匹配的活动了。
总结:
1.在配置文件中,给你需要跳转的活动加入一个action以及一个默认的category
2.在配置文件中,给你需要跳转的活动加入其他的category,用于更精准的匹配
3.在你需要切换活动的按钮里面,实例化一个Intent对象,并且为这个对象设置action以及加入category。 使用setAction 以及addCategory两个方法
4.把这个Intent对象,放入startActivity方法中启动活动。
向下一个活动传递数据
很多时候,两个活动之间是有紧密联系的,如果我们希望第一个活动能够给第二个活动传递一些数据的话,又该怎么做呢?
***1.在按钮1的点击监听事件方法中,修改代码为下面
btn_display.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,Display_intent.class);
intent.putExtra("data1","this is from MainActivity");
startActivity(intent);
}
});
这里面使用intent的putExtra方法,这个方法使用键值对的形式,接收两个参数。第一个参数是键,键必须是字符串,起到标识符的作用。第二个参数是值,值的类型可以是int,String,boolean等等
***2.在Display_intent活动的onCreate方法中,加入如下代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_intent);
Intent intent = getIntent();
String data = intent.getStringExtra("data1");
Log.d(Tag,data);
}
这里面使用getIntent来获得启动这个活动的intent对象。然后调用intent的getXXXExtra方法,这个方法接收一个参数,即键。代表想要获得的数据的”标识符“。XXX是获得的数据的类型。这里面因为传入的数据是字符串类型,所以调用getStringExtra,如果是一个int类型,就是intent.getIntExtra()。
注:intent.getIntExtra()方法,接收两个参数,第一个任然是键,第二个是默认值,即如果没有这个键返回一个默认值。
运行程序,点击按钮1进入到第二个活动,可以在日志中看到
说明活动1成功的向活动2传入了字符串。
带数据的返回上一个活动
如果只能开启这个活动的活动传递数据给它,而这个活动不能返回给开启它的活动数据,这很显然是不符合实际的。所以,我们也可以让这个活动在结束或者主动结束的时候返回给开启它的活动一些数据。
这里我们先在第二个活动的布局文件中加入一个按钮,用于点击这个按钮的时候就结束活动并且返回到上一个活动。
***1.活动2的布局文件代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_display_intent"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.asus.study_activity.Display_intent">
<Button
android:id="@+id/btn_finish"
android:text="返回"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
***2.在活动2的onCreate方法中,加入如下代码用于结束活动并返回一个字符串给第一个活动
Button btn_finish = (Button)findViewById(R.id.btn_finish);
btn_finish.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent1 = new Intent();
intent1.putExtra("return data","this is from Display_intent");
setResult(RESULT_OK,intent1);
finish();
}
});
里面四行代码,一二行已经说了很多次。第三行,是调用setResult方法,这个方法用于在活动销毁的时候,向上一个活动返回数据的。它接收两个参数,第一个参数为结果码,只要是唯一的int类型即可,但是一般使用RESULT_OK 或 RESULT_CANCELED 这两个结果码。第二个参数是一个Intent类型,这个Intent对象里面存放了需要返回的数据。
***3.在活动1中重写活动的回调方法。代码如下
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode){
case 1:
if (resultCode == RESULT_OK){
String string = data.getStringExtra("return data");
Log.d(Tag,string);
}
break;
}
}
同时,在按钮1的监听事件中,修改代码如下
btn_display.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,Display_intent.class);
intent.putExtra("data1","this is from MainActivity");
startActivityForResult(intent,1);
}
});
在这里,首先解释一下,因为要从第二个活动中返回数据给第一个活动,所以在第一个活动开启第二个活动的方式,是使用你startActivityForResult方法,这是一个带回调的开启活动,接收两个参数,第一个参数是intent,第二个参数是请求码,这里请求码是唯一的,如果你想要切换两个以上的活动,每一个活动都要有自己唯一的请求码。调用这个方法,当你启动的活动结束的时候,会自动去执行活动的回调方法,onActivityResult。重写这个方法,在里面根据请求码,即判断是哪一个活动返回的,再判断结果码,之前在第二个活动的地方使用setResult里面的结果码。最后在里面实现你需要的逻辑。当第二个点击按钮返回到活动1的时候,活动1就会自动执行回调结果的方法。然后在里面通过请求码判断出是第二个活动返回,再根据结果码,得到一个字符串并在日志中打印出来。
可以在日志中看到如下信息
BACK键销毁活动
很多时候,用户更喜欢的是按一下BACK键来返回,而不是按你设计的按钮,使用上面的例子,你会发现,你按下BACK键返回到上一个活动,但是在日志里面没有显示从上一个活动得到的数据。其实安卓早就帮我们考虑到了这个问题,我们只需要重写一下第二个活动里面的onBackPressed()方法,在里面实现我们自己的逻辑即可。
在活动2里面,重写onBackPressed()方法如下
@Override
public void onBackPressed() {
super.onBackPressed();
Intent intent1 = new Intent();
intent1.putExtra("return data","this is from Display_intent");
setResult(RESULT_OK,intent1);
finish();
}
这样,当按下BACK键返回的时候,也可以在日志中看到从第二个活动返回来的数据。
到这里,我对于活动的笔记就差不多整理完了,文中如有不对之处,欢迎指出。