[Android][第一行代码][第 2 章 Activity]

来源:互联网 发布:章台之柳 知乎 编辑:程序博客网 时间:2024/05/23 19:04

01. 菜单

  1. 创建菜单文件

    <?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>
  2. 在 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

  1. 显式 Intent

  2. 隐式 Intent

    • action 每个 Intent 中只能指定一个 action
    • category 每个 Intent 中可以指定多个 category
    • data
  3. data 详解

    • android:scheme 用于指定数据的协议部分。
    • android:host 用于指定数据的主机名部分。
    • android:port 用于指定数据的端口部分。
    • android:path 用于指定主机名和端口之后部分。
    • android:mimeType 用于指定可处理的数据类型,允许使用通配符的方式进行指定。
  4. 注意:

    • android.intent.categore.DEFAULT 是一种默认的 category 在调用 startActivity() 方法的时候会自动将这个 category 添加到 Intent 当中。
    • 只有<action><category>中的内容同时能够匹配上 Intent 中指定的 action 和 category 时,活动才能响应该 Intent。
    • 只有<data>标签中指定的内容和 Intent 中携带的 Data 完全一致是,当前活动才能够响应该 Intent。
  5. 启动浏览器

    Intent browserIntent = new Intent(Intent.ACTION_VIEW);browserIntent.setData(Uri.parse("https://www.baidu.com"));startActivity(browserIntent);
  6. 启动拨号

    Intent dialIntent = new Intent(Intent.ACTION_DIAL);dialIntent.setData(Uri.parse("tel:10086"));startActivity(dialIntent);

03. Activity 的生命周期

  1. 返回栈

    其实 Android 是使用任务(Task)来管理活动的,一个任务就是一组存放在里的活动的集合,这个栈也被称作返回栈(Back Stack)。栈是一种后进先出的数据接口。

  2. 活动状态

    1. 运行状态
      • 栈顶,可见,可交互
    2. 暂停状态
      • 栈中,可见,不可交互
    3. 停止状态
      • 栈中,不可见,不可交互
    4. 销毁状态
      • 出栈
  3. 生命周期函数

    • onCreat()
      • 初始化操作,加载布局,绑定事件等。
    • onStart()
      • 活动由不可见变为了可见。
    • onResume()
      • 活动准备好和用户进行交互。
    • onPause()
      • 这个方法在系统准备去启动或者恢复另一个活动的时候调用。我们通常会在这个方法中将一些消耗 CPU 的资源释放掉,以及保存一些关键数据,但这个方法的执行速度一定要快,不然会影响到新的栈顶活动的使用。
    • onStop()
      • 活动完全不可见。如果启动的新活动是一个对话框式的活动,那么 onPause() 执行 onStop() 不执行。
    • onDestroy()
      • 活动被销毁之前调用。
    • onRestart()
      • 活动由停止状态变为运行状态之前调用。
  4. 活动的生存期

    • 完整生存期
    • 可见生存期
    • 前台生存期

04. 生命周期图

Activity_Lifecycle

05. 活动被回收

  1. 场景:应用中有一个活动 A,用户在活动 A 的基础上启动了活动 B,活动 A 就进入了停止状态,这个时候由于系统内存不足,将活动 A 回收掉了,然后用户按下 Back 键返回活动 A,会出现什么情况?会正常显示活动 A 但不会执行活动 A 的 onRestart() 方法,而是会执行 onCreate() 方法将活动 A 重新创建一次。

    问题:打个比方,活动 A 中有一个文本输入框,用户输入一段文字,然后启动了活动 B,这时候活动 A 被回收了,按下 Back 键返回活动 A,却发现输入的文字全部都没了。数据怎么存储?

  2. 生命周期回调:

    // 启动活动 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()
  3. 解决方法:Activity 中提供了一个 onSaveInstanceState() 方法,可以保证活动被回收之前一定会被调用。在活动的 onCreate() 方法中有一个对应的 Bundle 类型参数 saveInstanceState 从中获取保存的数据。

  4. 实现代码:

     @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); }
  5. 测试方法

    第一步,打开开发者选项;第二步,勾选不保留活动用户离开后即销毁每个活动。

  6. 测试发现

    在测试中使用 EditText 测试 Activity 被系统回收,但发现返回之后 Activity 和 EditText 的确都是被重新创建了,但是 EditText 中输入的内容却仍然存在。其实是 View 有类似的保存数据的效果。

  7. 其他

    • 关于开发者选项中的启用严格模式
    • Android 中正确保存view的状态
    • View的onSaveInstanceState和onRestoreInstanceState过程分析
    • 如何保存和恢复 Activity 状态

06. 启动模式

  1. 四种启动模式
    • standard
    • singleTop
    • singleTask
    • singleInstance
  2. 指定为 singleInstance 模式的活动会启用一个新的返回栈来管理这个活动(其实如果 singTask 模式指定了不同的 taskAffinity,也会启动一个新的返回栈)。程序中有一个活动是允许其他程序调用的,则使用此模式。其他三种不能实现是因为每个应用都会有自己的返回栈,同一个活动在不同的返回栈中入栈时必须是创建了新的实例。

07. 活动的实践

  1. 获取 Activity 的 Task id

    this.getTaskId();
  2. 获取 Activity 的名字

    this.getClass().getSimpleName();
  3. 杀死当前进程

    android.os.Process.killProcess(android.os.Process.myPid());// 删掉当前进程
  4. 活动管理集合

    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());// 删掉当前进程 }}
  5. 启动活动

    /*** 其他活动启动当前获取** @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. 小结

  1. 关于向下兼容的 AppCompatActivity 需要学习。
  2. 关于的相关知识需要学习总结。
  3. 弹出 Dialog 或者 PopupWindow不影响 Activity 的生命周期。
  4. 开发者选项中的各个功能的使用方式。
  5. 和启动模式相关的有一个 onNewIntent(Intent intent) 方法需要注意。
  6. Activity 的 taskAffinity 属性。
  7. 随时随地退出程序。
  8. 启动活动的最佳写法。
  9. 退出程序的相关问题,如何真正退出程序,杀掉进程,最优做法是什么?
原创粉丝点击