返回栈概念:
   Android 是使用任务(Task)来管理活动的,一个任务就是一组存放在栈里的活动
 的集合,这个栈也被称作返回栈(Back Stack) 。栈是一种后进先出的数据结构,在默认情况
 下,每当我们启动了一个新的活动,它会在返回栈中入栈,并处于栈顶的位置。而每当我们
 按下 Back 键或调用 finish()方法去销毁一个活动时,处于栈顶的活动会出栈,这时前一个入
 栈的活动就会重新处于栈顶的位置。系统总是会显示处于栈顶的活动给用户。    

 

    一、项目文件夹的说明
1.  src
毫无疑问,src 目录是放置我们所有 Java 代码的地方,它在这里的含义和普通 Java
项目下的 src 目录是完全一样的,展开之后你将看到我们刚才创建的 HelloWorldActivity
文件就在里面。
2.  gen
这个目录里的内容都是自动生成的,主要有一个 R.java 文件,你在项目中添加的任
何资源都会在其中生成一个相应的资源 id。这个文件永远不要手动去修改它。
3.  assets
这个目录用得不多,主要可以存放一些随程序打包的文件,在你的程序运行时可以
动态读取到这些文件的内容。另外,如果你的程序中使用到了 WebView 加载本地网页
的功能,所有网页相关的文件也都存放在这个目录下。
4.  bin
这个目录你也不需要过多关注,它主要包含了一些在编译时自动产生的文件。其中
会有一个你当前项目编译好的安装包,展开 bin 目录你会看到 HelloWorld.apk,把这个
文件拷到手机上就可以直接安装了。
5.  libs
如果你的项目中使用到了第三方 Jar包, 就需要把这些 Jar包都放在 libs目录下, 放
在这个目录下的 Jar 包都会被自动添加到构建路径里去。 你可以展开上图中 Android 4.0、
Android Private Libraries、Android Dependencies这些库,其中显示的 Jar 包都是已经被
添加到构建路径里的。
6.  res
这个目录下的内容就有点多了,简单点说,就是你在项目中使用到的所有图片、布
局、字符串等资源都要存放在这个目录下,前面提到的 R.java 中的内容也是根据这个目
录下的文件自动生成的。 当然这个目录下还有很多的子目录, 图片放在 drawable目录下,
布局放在 layout 目录下,字符串放在 values 目录下,所以你不用担心会把整个 res目录
弄得乱糟糟的。
7.  AndroidManifest.xml
这是你整个 Android项目的配置文件,你在程序中定义的所有四大组件都需要在这
个文件里注册。另外还可以在这个文件中给应用程序添加权限声明,也可以重新指定你
创建项目时指定的程序最低兼容版本和目标版本。由于这个文件以后会经常用到,我们
用到的时候再做详细说明。
8.  project.properties
这个文件非常地简单,就是通过一行代码指定了编译程序时所使用的 SDK 版本。
我们的 HelloWorld项目使用的是 API 14,你也可以在这里改成其他版本试一试。
这样整个项目的目录结构就都介绍完了,如果你还不能完全理解的话也很正常,毕竟里
面有太多的东西你都还没接触过。不用担心,这并不会影响到你后面的学习。相反,等你学
完整本书后再回来看这个目录结构图时,你会觉得特别地清晰和简单。

 
    二、日志工具的说明
1.  Log.v()
这个方法用于打印那些最为琐碎的,意义最小的日志信息。对应级别 verbose,是
Android 日志里面级别最低的一种。
2.  Log.d()
这个方法用于打印一些调试信息, 这些信息对你调试程序和分析问题应该是有帮助
的。对应级别 debug,比 verbose高一级。
3.  Log.i()
这个方法用于打印一些比较重要的数据,这些数据应该是你非常想看到的,可以帮
你分析用户行为的那种。对应级别 info,比 debug高一级。
4.  Log.w()
这个方法用于打印一些警告信息,提示程序在这个地方可能会有潜在的风险,最好
去修复一下这些出现警告的地方。对应级别 warn,比 info高一级。
5.  Log.e()
这个方法用于打印程序中的错误信息,比如程序进入到了 catch 语句当中。当有错
误信息打印出来的时候,一般都代表你的程序出现严重问题了,必须尽快修复。对应级
别 error,比 warn高一级。

    三、开发中的小细节
1.隐藏标题栏:
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 requestWindowFeature(Window.FEATURE_NO_TITLE); //不在活动中显示标题栏
 setContentView(R.layout.first_layout);
}
2.Toast提醒方式使用:

    四、活动状态
1.运行状态
 当一个活动位于返回栈的栈顶时,这时活动就处于运行状态。系统最不愿意回收的
 就是处于运行状态的活动,因为这会带来非常差的用户体验。
2.  暂停状态
 当一个活动不再处于栈顶位置,但仍然可见时,这时活动就进入了暂停状态。你可
 能会觉得既然活动已经不在栈顶了, 还怎么会可见呢?这是因为并不是每一个活动都会
 占满整个屏幕的,比如对话框形式的活动只会占用屏幕中间的部分区域,你很快就会在
 后面看到这种活动。处于暂停状态的活动仍然是完全存活着的,系统也不愿意去回收这
 种活动(因为它还是可见的,回收可见的东西都会在用户体验方面有不好的影响) ,只
 有在内存极低的情况下,系统才会去考虑回收这种活动。
3.  停止状态
 当一个活动不再处于栈顶位置,并且完全不可见的时候,就进入了停止状态。系统
 仍然会为这种活动保存相应的状态和成员变量,但是这并不是完全可靠的,当其他地方
 需要内存时,处于停止状态的活动有可能会被系统回收。
4.  销毁状态
 当一个活动从返回栈中移除后就变成了销毁状态。 系统会最倾向于回收处于这种状
 态的活动,从而保证手机的内存充足。

    五、活动的生存周期
1.onCreate()
 这个方法你已经看到过很多次了,每个活动中我们都重写了这个方法,它会在活动
 第一次被创建的时候调用。你应该在这个方法中完成活动的初始化操作,比如说加载布
 局、绑定事件等。
2.  onStart()
 这个方法在活动由不可见变为可见的时候调用。
3.  onResume()
 这个方法在活动准备好和用户进行交互的时候调用。 此时的活动一定位于返回栈的
 栈顶,并且处于运行状态。
4.  onPause()
 这个方法在系统准备去启动或者恢复另一个活动的时候调用。 我们通常会在这个方
 法中将一些消耗 CPU 的资源释放掉,以及保存一些关键数据,但这个方法的执行速度
 一定要快,不然会影响到新的栈顶活动的使用。
5.  onStop()
 这个方法在活动完全不可见的时候调用。它和 onPause()方法的主要区别在于,如
 果启动的新活动是一个对话框式的活动,那么 onPause()方法会得到执行,而 onStop()
 方法并不会执行。
6.  onDestroy()
 这个方法在活动被销毁之前调用,之后活动的状态将变为销毁状态。
7.  onRestart()
 这个方法在活动由停止状态变为运行状态之前调用,也就是活动被重新启动了。
8.  onSaveInstanceState(Bundle outState)
 这个方法会保证一定在活动被系统回收之前调用, 因此我们可以通过这个方法来解决活动被回收时
 临时数据得不到保存的问题。被保存的数据会在onCreate(Bundle savedInstanceState)中传入,通过Bundle来获取。

以上七个方法中除了 onRestart()方法,其他都是两两相对的,从而又可以将活动分为三
 种生存期。
1.  完整生存期
 活动在 onCreate()方法和 onDestroy()方法之间所经历的,就是完整生存期。一般情
 况下,一个活动会在 onCreate()方法中完成各种初始化操作,而在 onDestroy()方法中完
 成释放内存的操作。
2.  可见生存期
 活动在 onStart()方法和 onStop()方法之间所经历的,就是可见生存期。在可见生存
 期内,活动对于用户总是可见的,即便有可能无法和用户进行交互。我们可以通过这两
 个方法,合理地管理那些对用户可见的资源。比如在 onStart()方法中对资源进行加载,
 而在 onStop()方法中对资源进行释放, 从而保证处于停止状态的活动不会占用过多内存。
3.  前台生存期
 活动在 onResume()方法和 onPause()方法之间所经历的,就是前台生存期。在前台
 生存期内,活动总是处于运行状态的,此时的活动是可以和用户进行相互的,我们平时
 看到和接触最多的也这个状态下的活动。

   六、活动的启动模式
 启动模式一共有四种,分别是 standard、singleTop、singleTask 和 singleInstance,可以在 AndroidManifest.xml 中通过给<activity>标签指定
 android:launchMode属性来选择启动模式。
1.standard
  standard 是活动默认的启动模式,在不进行显式指定的情况下,所有活动都会自动使用
 这种启动模式。因此,到目前为止我们写过的所有活动都是使用的 standard模式。经过上一
 节的学习,你已经知道了 Android 是使用返回栈来管理活动的,在 standard 模式(即默认情
 况)下,每当启动一个新的活动,它就会在返回栈中入栈,并处于栈顶的位置。对于使用
 standard 模式的活动,系统不会在乎这个活动是否已经在返回栈中存在,每次启动都会创建
 该活动的一个新的实例。

2.singleTop
  可能在有些情况下,你会觉得 standard模式不太合理。活动明明已经在栈顶了,为什么
 再次启动的时候还要创建一个新的活动实例呢?别着急, 这只是系统默认的一种启动模式而
 已,你完全可以根据自己的需要进行修改,比如说使用 singleTop 模式。当活动的启动模式
 指定为 singleTop, 在启动活动时如果发现返回栈的栈顶已经是该活动, 则认为可以直接使用
 它,不会再创建新的活动实例。如果栈顶不是该活动时,还是会重新创建该活动的。

3.singleTask
  使用 singleTop 模式可以很好地解决重复创建栈顶活动的问题,但是正如你在上一节所
 看到的,如果该活动并没有处于栈顶的位置,还是可能会创建多个活动实例的。那么有没有
 什么办法可以让某个活动在整个应用程序的上下文中只存在一个实例呢?这就要借助
 singleTask模式来实现了。当活动的启动模式指定为 singleTask,每次启动该活动时系统首先
 会在返回栈中检查是否存在该活动的实例,如果发现已经存在则直接使用该实例,并把在这
 个活动之上的所有活动统统出栈,如果没有发现就会创建一个新的活动实例。

4.singleInstance
  singleInstance 模式应该算是四种启动模式中最特殊也最复杂的一个了, 你也需要多花点
 功夫来理解这个模式。 不同于以上三种启动模式, 指定为 singleInstance 模式的活动会启用一
 个新的返回栈来管理这个活动(其实如果 singleTask模式指定了不同的 taskAffinity,也会启
 动一个新的返回栈) 。那么这样做有什么意义呢?想象以下场景,假设我们的程序中有一个
 活动是允许其他程序调用的, 如果我们想实现其他程序和我们的程序可以共享这个活动的实
 例,应该如何实现呢?使用前面三种启动模式肯定是做不到的,因为每个应用程序都会有自
 己的返回栈,同一个活动在不同的返回栈中入栈时必然是创建了新的实例。而使用
 singleInstance 模式就可以解决这个问题, 在这种模式下会有一个单独的返回栈来管理这个活
 动,不管是哪个应用程序来访问这个活动,都共用的同一个返回栈,也就解决了共享活动实
 例的问题。(可在活动中调用getTaskId()来查看该活动在哪个栈中)

活动生命周期图:

android ndk 返回byte数组 安卓返回栈_Android