[Android][第一行代码][第 2 章 Activity]
来源:互联网 发布:章台之柳 知乎 编辑:程序博客网 时间:2024/05/23 19:04
01. 菜单
创建菜单文件
<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/menu_add" android:title="Add" /> <item android:id="@+id/menu_remove" android:title="Remove" /></menu>
在 Activity 中进行添加和处理
/** * 创建自定义菜单 * * @param menu 系统指定的菜单对象 * @return true, 表示允许创建的菜单显示出来 */ @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu, menu);// 从资源中加载菜单 return true;// 允许菜单显示 } /** * 菜单 Item 的点击事件 * * @param item 菜单 Item * @return */ @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_add: ToastUtil.showShortToast(this, "Add"); break; case R.id.menu_remove: ToastUtil.showShortToast(this, "Remove"); break; } return true; }
02. Intent
显式 Intent
隐式 Intent
- action 每个 Intent 中只能指定一个 action
- category 每个 Intent 中可以指定多个 category
- data
data 详解
- android:scheme 用于指定数据的协议部分。
- android:host 用于指定数据的主机名部分。
- android:port 用于指定数据的端口部分。
- android:path 用于指定主机名和端口之后部分。
- android:mimeType 用于指定可处理的数据类型,允许使用通配符的方式进行指定。
注意:
android.intent.categore.DEFAULT
是一种默认的 category 在调用startActivity()
方法的时候会自动将这个 category 添加到 Intent 当中。- 只有
<action>
和<category>
中的内容同时能够匹配上 Intent 中指定的 action 和 category 时,活动才能响应该 Intent。 - 只有
<data>
标签中指定的内容和 Intent 中携带的 Data 完全一致是,当前活动才能够响应该 Intent。
启动浏览器
Intent browserIntent = new Intent(Intent.ACTION_VIEW);browserIntent.setData(Uri.parse("https://www.baidu.com"));startActivity(browserIntent);
启动拨号
Intent dialIntent = new Intent(Intent.ACTION_DIAL);dialIntent.setData(Uri.parse("tel:10086"));startActivity(dialIntent);
03. Activity 的生命周期
返回栈
其实 Android 是使用任务(Task)来管理活动的,一个任务就是一组存放在栈里的活动的集合,这个栈也被称作返回栈(Back Stack)。栈是一种后进先出的数据接口。
活动状态
- 运行状态
- 栈顶,可见,可交互
- 暂停状态
- 栈中,可见,不可交互
- 停止状态
- 栈中,不可见,不可交互
- 销毁状态
- 出栈
- 运行状态
生命周期函数
- onCreat()
- 初始化操作,加载布局,绑定事件等。
- onStart()
- 活动由不可见变为了可见。
- onResume()
- 活动准备好和用户进行交互。
- onPause()
- 这个方法在系统准备去启动或者恢复另一个活动的时候调用。我们通常会在这个方法中将一些消耗 CPU 的资源释放掉,以及保存一些关键数据,但这个方法的执行速度一定要快,不然会影响到新的栈顶活动的使用。
- onStop()
- 活动完全不可见。如果启动的新活动是一个对话框式的活动,那么
onPause()
执行onStop()
不执行。
- 活动完全不可见。如果启动的新活动是一个对话框式的活动,那么
- onDestroy()
- 活动被销毁之前调用。
- onRestart()
- 活动由停止状态变为运行状态之前调用。
- onCreat()
活动的生存期
- 完整生存期
- 可见生存期
- 前台生存期
04. 生命周期图
05. 活动被回收
场景:应用中有一个活动 A,用户在活动 A 的基础上启动了活动 B,活动 A 就进入了停止状态,这个时候由于系统内存不足,将活动 A 回收掉了,然后用户按下 Back 键返回活动 A,会出现什么情况?会正常显示活动 A 但不会执行活动 A 的 onRestart() 方法,而是会执行 onCreate() 方法将活动 A 重新创建一次。
问题:打个比方,活动 A 中有一个文本输入框,用户输入一段文字,然后启动了活动 B,这时候活动 A 被回收了,按下 Back 键返回活动 A,却发现输入的文字全部都没了。数据怎么存储?
生命周期回调:
// 启动活动 AJustDo23: RecoveryActivity ---> onCreate()JustDo23: RecoveryActivity ---> onStart()JustDo23: RecoveryActivity ---> onResume()// 在活动 A 的基础上启动活动 BJustDo23: RecoveryActivity ---> onPause()JustDo23: RecoveryActivity ---> onSaveInstanceState()JustDo23: RecoveryActivity ---> onStop()JustDo23: RecoveryActivity ---> onDestroy()// 按下 Back 键返回活动 AJustDo23: RecoveryActivity ---> onCreate()JustDo23: RecoveryActivity ---> tempData = Something you just typedJustDo23: RecoveryActivity ---> onStart()JustDo23: RecoveryActivity ---> onResume()
解决方法:Activity 中提供了一个 onSaveInstanceState() 方法,可以保证活动被回收之前一定会被调用。在活动的 onCreate() 方法中有一个对应的 Bundle 类型参数 saveInstanceState 从中获取保存的数据。
实现代码:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_recovery); if (savedInstanceState != null) {// 取出保存的数据 String tempData = savedInstanceState.getString("data_key"); LogUtils.e(simpleName + " ---> " + "tempData = " + tempData); } } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState);// 在销毁前进行的数据保存 String tempData = "Something you just typed"; outState.putString("data_key", tempData); }
测试方法
第一步,打开开发者选项;第二步,勾选不保留活动用户离开后即销毁每个活动。
测试发现
在测试中使用 EditText 测试 Activity 被系统回收,但发现返回之后 Activity 和 EditText 的确都是被重新创建了,但是 EditText 中输入的内容却仍然存在。其实是 View 有类似的保存数据的效果。
其他
- 关于开发者选项中的启用严格模式
- Android 中正确保存view的状态
- View的onSaveInstanceState和onRestoreInstanceState过程分析
- 如何保存和恢复 Activity 状态
06. 启动模式
- 四种启动模式
- standard
- singleTop
- singleTask
- singleInstance
- 指定为 singleInstance 模式的活动会启用一个新的返回栈来管理这个活动(其实如果 singTask 模式指定了不同的 taskAffinity,也会启动一个新的返回栈)。程序中有一个活动是允许其他程序调用的,则使用此模式。其他三种不能实现是因为每个应用都会有自己的返回栈,同一个活动在不同的返回栈中入栈时必须是创建了新的实例。
07. 活动的实践
获取 Activity 的 Task id
this.getTaskId();
获取 Activity 的名字
this.getClass().getSimpleName();
杀死当前进程
android.os.Process.killProcess(android.os.Process.myPid());// 删掉当前进程
活动管理集合
public class ActivityCollector { public static List<Activity> activityList = new ArrayList<>(); public static void addActivity(Activity activity) { activityList.add(activity); } public static void removeActivity(Activity activity) { activityList.remove(activity); } public static void finishAll() { for (Activity activity : activityList) { if (!activity.isFinishing()) { activity.finish(); } } activityList.clear(); android.os.Process.killProcess(android.os.Process.myPid());// 删掉当前进程 }}
启动活动
/*** 其他活动启动当前获取** @param context 上下文* @param data1 传递数据* @param data2 传递数据*/public static void actionStart(Context context, String data1, String data2) { Intent intent = new Intent(context, StartActivity.class); intent.putExtra("param1", data1); intent.putExtra("param2", data2); context.startActivity(intent);}
08. 小结
- 关于向下兼容的 AppCompatActivity 需要学习。
- 关于栈和堆的相关知识需要学习总结。
- 弹出 Dialog 或者 PopupWindow 并不影响 Activity 的生命周期。
- 在开发者选项中的各个功能的使用方式。
- 和启动模式相关的有一个 onNewIntent(Intent intent) 方法需要注意。
- Activity 的 taskAffinity 属性。
- 随时随地退出程序。
- 启动活动的最佳写法。
- 退出程序的相关问题,如何真正退出程序,杀掉进程,最优做法是什么?
- [Android][第一行代码][第 2 章 Activity]
- 第一行代码Android-------Activity
- 活动(Activity)---《第一行代码Android》笔记
- Android Studio 手动创建活动(Activity) 第一行代码 第二章
- 第一行代码 第二章 Activity
- 第一行代码,Activity部分
- 第一行代码笔记 Activity
- Android第一行代码
- 第一行代码 读书笔记 第2章
- 第一行代码+Android+第2版 笔记第三天
- 【第一行代码】Android 活动(activity)总结
- 第一行代码Android学习笔记(一)activity
- 启动Activity的最佳写法--《第一行代码Android》
- 入门Android开发--第一行代码--笔记系列(Activity)
- Android——《第一行代码》之Activity
- Android-第一行代码学习笔记——activity
- Android第一行代码笔记 Activity的一些基础知识
- 《第一行代码2》
- meta标签的一些用法
- VS2015 远程调试方法
- spring框架中的单例Beans是线程安全的么?
- Hibernate的查询(略)
- Scrapy模块
- [Android][第一行代码][第 2 章 Activity]
- FreeRTOS移植教程 STM32 -- Cortex M3
- QT自定义控件:CircleProgressBar环形进度条
- Address already in use: JVM_Bind<null>:8080错误的解决办法
- HDU-2017"百度之星"程序设计大赛-复赛-1006-Valley Numer II
- 《心情》 致敬24岁的自己
- Spring boot security
- NYOJ42一笔画问题
- Oracle创建的序列从2开始自增的解决办法