0. 什么是Activity
Activity
是一个应用组件,用户可与其提供的屏幕进行交互,以执行拨打电话、拍摄照片、发送电子邮件或查看地图等操作。 每个 Activity 都会获得一个用于绘制其用户界面的窗口。窗口通常会充满屏幕,但也可小于屏幕并浮动在其他窗口之上。
1. 创建活动
Android Studio在创建项目的时候如果不选择 Add No Activity,会自动帮我们创建出一个主活动,而这在实际活动中是远远不够的。
当我们想手动添加Activity的时候,有以下两种方式:
- 自动创建
- 手动创建
1.1 自动创建
直接在Android Studio中的Java项目文件夹下点击创建Activity
,如下图所示,强大的Android Studio会自动创建好Activity
和其所需要的配置文件。
这种方式能创建出来Activity的大体框架,实为方便,在工作中能提高不少效率
1.2 手动创建
一个Activity
的引入分为3个步骤
- 类
- 页面
- 注册
类:首先需要在Java项目目录下创建一个Java类,这个类需要继承AppCompactActivity
public class FirstActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(SavedInstance);
}
}
在这个类中,必须要重写[onCreate()]
接口,关于[onCreate()]
的具体用法和作用,后面会详细讲到
页面:在目录下创建一个 layout resource file,这个xml文件主要用来展示页面的样式,也就是App中用户看到的那个样子。
我们看看这个layout文件的大概样子
可以看到,这个xml文件中包干了一个LinearLayout
标签,其中的属性包括xmlns:android
,android:layout_width
,android:layout_height
,android:orientation
,分别用来指定页面的 NameSpace,宽度,高度,排列方向
同时,这个xml文件有两种浏览方式,一种是如上的Text视图,一种是Design视图,可以让开发者直接看到页面上的布局和样式,如下所示
其中有几点需要注意
- 可以进行Text和Design两种视图的切换
- 每个layout文件都需要有一个布局模式根节点,例如LinearLayout等
注册:在目录下有一个AndroidManifest.xml文件,这个文件主要用来注册所有的活动,活动也只有注册之后才能使用。
如果想将一个活动注册为主活动,可以指定相应的action
和 category
,如下代码所示
在后续我们使用intent
来对活动进行操作时,会继续对Manifest进行编辑,这里只需要掌握大概定义和写法就够了
2. Activity生命周期
这张图代表了Activity
的从创建、执行到销毁的全过程,其中可以看到,经过的周期分为7个部分,分别是:
-
onCreate()
在活动第一次被创建的时候调用,主要完成初始化操作,例如加载布局、绑定事件等 -
onStart()
活动不可见变为可见的时候调用 -
onResume()
当活动与返回栈的栈顶,并且处于运行状态时调用 -
onPause()
在系统准备去启动或者回复另一个活动时调用。通常会在这个方法中将一些小号CPU的资源释放掉,以及保存一些关键数据 -
onStop()
在活动完全不可见的时候调用 -
onDestroy()
被销毁之前调用,然后活动变为销毁 -
onRestarrt()
被重新启动
一些常见事件执行的生命周期
1. 跳转其他活动:onPause()
,onStop()
2. 返回活动:onRestarrt()
,onStart()
,onResume()
3. 第一次被创建:onCreate()
,onStart()
,onResume()
4. 跳转Dialog: onPause()
5. 退出应用:onPause()
,onStop()
, onDestroy()
3. Activity数据流
3.1 Activity数据保存
当重新进入应用的时候,Activity会经历onCreate()
方法,因此会将以前操作的数据全部抹掉,这极不利于用户体验。为了解决这一问题,我们使用onSaveInstanceState()
方法来对Activity数据进行保存。
onSaveInstanceState(Bundle outState)
:回调方法,在活动被回收之前一定被调用,outstate
用来接收所保存的内容
@Override
protected void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
String tempData = "Something you just typed";
outState.putString("data_key", tempData);
}
这样就可以在onCreate()
中接收并且使用
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null) {
String tempData = savedInstanceState.getString("data_key");
Log.d(TAG,tempData);
}
}
3.2 返回数据给上一个活动
可以使用startActivityForResult()
来给上一个活动传递数据。
startActivityForResult()
启动的活动在销毁时会回调一个onActivityResult()
方法,可以用来接受下一个活动传回来的数据。
First Activity
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
switch (requestCode){
case 1:
if(resultCode == RESULT_OK){
String returnedData = data.getStringExtra("data_return");
Log.d("FirstActivity", returnedData);
}
break;
default:
}
}
Second Activity 注意setResult方法
@Override
public void onBackPressed() {
Intent intent = new Intent();
intent.putExtra("data_return","Hello First Activity");
setResult(RESULT_OK,intent);
finish();
}
3.3 给下一个活动传递数据
可以利用Intent
向下一个活动传递数据,Intent
中有putExtra()
方法,用于放入传递的数据,下一个活动可以利用getIntent()
拿到传进来的Intent对象,并调用Intent
中的getString()
getBoolean()
等方法来获取数据。
putExtra(key,value)
存如键值对
value = intent.getString(key)
通过键获取值
4. Intent
4.1 显示Intent
显式Intent
意图非常明显的Intent,直接指定在谁的环境中,打开哪个Activity
Intent构造函数一共有5种
-
new Intent(Intent o)
复制构造函数 -
new Intent(context,class)
直接传入当前上下文和下一个活动的class -
new Intent(action)
给定action来操作 -
new Intent(action, URI)
利用指定的action来操作给定的URI
-
new Intent(action, URI,context,class)
利用给定的操作和数据为给定的组件创建Intent
。
4.2 隐式Intent
隐式Intent
意图不明显的Intent,而是制定了一系列更为抽象地action
和category
等信息,然后由系统分析这个Intent
,并帮助分析启动哪个
使用隐式Intent的步骤如下:
- 创建隐式Intent
隐式Intent的创建方法在上面构造函数已经包括了,就是调用new Intent(action)
来指定想要访问的action
,如果想要添加category
,那么只需要调用intent
的addCategory()
方法就可以了
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent_start = new Intent("com.example.activitytest.ACTION_START");
intent_start.addCategory("com.example.activitytest.MY_CATEGORY");
startActivity(intent_start);
}
});
- 添加action / category
指定了Intent
,当然要在系统中添加相应的action
和category
。我们需要做的是在AndroidManifest.xml文件中添加如下的代码
这样就会为我们寻找到具有相应action
和category
的Intent
,并跳转至这个Intent
常见的action
Intent.ACTION_MAIN
Intent.Action_CALL
Intent.Action.DIAL
Intent.ACTION_VIEW
显示用户数据
Uri uri=Uri.parse("geo:39.899533,116.036476"); //打开地图定位
Intent it = new Intent(Intent.ACTION_VIEW,uri);
startActivity(it);
Intent intent = new Intent(Intent.ACTION_VIEW); //播放视频
Uri uri = Uri.parse("file:///sdcard/media.mp4");
intent.setDataAndType(uri, "video/*");
startActivity(intent);
更多可以看这个链接 https://www.jianshu.com/p/c9b383caab02
5. 活动启动模式
5.1 standard
standard模式是Activity启动的标准模式,每一个打开的活动都会入栈,且会重复入栈
注:图片转载于 https://blog.csdn.net/zy_jibai/article/details/80587083
5.2 singleTop
singleTop是为了解决重复打开栈顶活动而生,当栈顶活动(Activity2)试图打开一个Activity2时,它不会创建新的Activity2。
注:图片转载于 https://blog.csdn.net/zy_jibai/article/details/80587083
如果要指定singleTop打开方式,需要在AndroidManifest.xml文件中标明android:launchMode="singleTop"
应用场景:
开启渠道多,适合多应用开启调用的Activity:通过这种设置可以避免已经创建过的Activity被重复创建
5.3 singleTask
singleTask用来解决在栈内创建多个活动实例的问题,它会自动搜寻栈内已有的Activity,如果匹配上,则跳转至对应的Activity,同时这个Activity上面所有的Activity出栈
注:图片转载于 https://blog.csdn.net/zy_jibai/article/details/80587083
应用场景:
程序主界面,我们肯定不希望主界面被多创建,而且在主界面退出的时候退出整个App是最好的设想。
5.4 singleInstance
在这种模式每个应用程序会有一个单独的返回栈,不管是哪个应用程序来访问这个活动,都共用的一个返回栈,可以解决活动共享的问题
注:图片转载于 https://blog.csdn.net/zy_jibai/article/details/80587083
6. Others
6.1 使用菜单栏
- 在res/menu目录下创建menu文件
- 重写
onCreateOptionsMenu()
和onOptionsItemSelected()
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
/**
* 处理菜单被选中后的后续处理
*/
public boolean onOptionsItemSelected(MenuItem munItem){
String s = munItem.getTitle().toString();//获取选中的标题的字符串
switch (munItem.getItemId()) {
case R.id.delete:
Toast.makeText(this, "你选中了"+s, Toast.LENGTH_LONG).show();//Toast浮动显示提示信息,不获得焦点
return true;
case R.id.add:
Toast.makeText(this, "你选中了"+s, Toast.LENGTH_LONG).show();
return true;
case R.id.find:
Toast.makeText(this, "你选中了"+s, Toast.LENGTH_LONG).show();
return true;
case R.id.name:
Toast.makeText(this, "你选中了"+s, Toast.LENGTH_LONG).show();
return true;
default:
return super.onOptionsItemSelected(munItem);
}
}
这次的总结先到这儿,下一次将总结一下《第一行代码》中的UI设计部分,谢谢大家~