现在的位置: 首页 > 综合 > 正文

android training 学习笔记001-android入门基础

2018年04月19日 ⁄ 综合 ⁄ 共 8404字 ⁄ 字号 评论关闭
文章目录

1.建立你的第一个App(Building Your First App)

  • Application Name:填写想呈现给用户的应用名称.
  • Project Name:是项目的文件夹名称和在Eclipse中显示的名称.
  • Package Name:是应用的包命名空间,,通常使用你所在公司组织或发布实体的反向域名作为包名。此处可以使用"com.example.myfirstapp" ,但是你不能在 Google Play上发布使用 "com.example"作为包名的应用.
  • Minimum Required SDK:用API level表示你的应用支持的最低Android版本,为了支持尽可能多的设备,设置为能支持你应用核心功能的最低API版本。如果某些非核心功能尽在较高版本的API支持,你可以只在支持这些功能的版本上开启它们(参考兼容不同的系统版本)。
  • Target SDK:表示你测试过你的应用支持的最高Android版本(同样用API level表示)。
  • Compile With:是你的应用将要编译的目标Android版本,把该值设为最新版本,使你可以使用Android的最新特性,同时可以在最新的设备上优化应用来提高用户体验。
发布应用之前,应确保你设计的图标符合Iconography中规定的设计规范。
appcompat_v7包是一个能让2.1以上系统使用上4.0版本的界面的支持库。更新 adt 到 22.6.0 以后新建的项目,如果 minsdk 小于 4.0 就会自动产生这个项目。
可选的布局文件:在XML中定义界面布局而不是在运行时去动态生成布局是有多个原因的,其中最重要的一个原因是这样可以使得你为不同大小的屏幕创建不同的布局文件。例如,你可以创建创建2个版本的布局文件,告诉系统在小的屏幕上使用其中一个布局文件,在大的屏幕上使用另外一个布局文件。缺点是使用 xml 布局会大大增加创建 view 的时间,因为使用 xml 布局创建的 view 需要先解析 xml 布局文件,然后再使用反射创建 view 对象。
android:layout_height 和 android:layout_width 的含义,一个 view 为什么有 layout_height 和 layout_width,不是 height 和 width 是因为 view 的长宽高是父 view 决定的,父 view 在他自己的 onLayout 方法调用子 view 的 layout 方法,传入上下左右四个坐标值,就决定了子 view 的大小和位置。
对于宽和高不建议指定具体的大小,使用wrap_content 指定之后,这个视图只是占据内容大小的空间。如果你使用了match_parent,这时 EditText 将会布满整个屏幕。
Fragments 把应用程序的功能和用户界面分解成可以复用的模块。
Activity 所有子类都必须实现 onCreate() 方法。创建 activity 的实例时系统会调用该方法,此时必须用 setContentView() 来设置Activity 的 view,来对 Activity 进行初始化。
<application ... >
    ...
    <activity
        android:name="com.example.myfirstapp.DisplayMessageActivity"
        android:label="@string/title_activity_display_message"
        android:parentActivityName="com.example.myfirstapp.MainActivity" >
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.myfirstapp.MainActivity" />
    </activity>
</application>
androidmanifest.xml 文件中 activity 节点的 android:parentActivityName 属性声明了在应用程序中该Activity逻辑层面的父类Activity的名称。 系统使用此值来实现默认导航操作,比如在Android 4.1(API level 16)或者更高版本中的Up navigation。

2.添加ActionBar(Adding the Action Bar)

Action Bar是 activity 的最重要的设计元素之一。它提供了多种 UI 特性,可以让你的 app 和其他 Android app 保持较多的一致性,为用户所熟悉。核心的功能包括:
  • 一个专门的空间用来显示你的app的标识,并且还可以指出目前所处在app的哪个页面。
  • 以一种可预见的方式访问重要的操作(比如检索)。
  • 支持导航和视图切换(通过Tabs和下拉列表)
Action bar 最基本的形式,就是为 activity 显示标题,并且在标题左边显示一个 app icon。
从 Android 3.0(API lever 11) 开始,所有使用 Theme.Holo 主题(或者它的子类)的activity 都包含了 action bar。
当 app 运行在 Andriod 3.0 以下版本(不低于 Android 2.1)时,如果要添加 action bar,需要加载 Android Support 库。1、更新 activity,以便于它继承于 ActionBarActivity。2、在 mainfest 文件中,更新 <application> 标签或者单一的 <activity> 标签来使用一个 Theme.AppCompat 主题。
Action bar 允许你为当前上下文中最重要的操作添加按钮。那些直接出现在 action bar 中的 icon 和/或文本被称作操作按钮。不匹配的或不足够重要的操作被隐藏在 action overflow 中。在 action overflow 里能展现额外的操作。

3.兼容不同的设备

为了支持多国语言,可以在 res/  的子目录上使用 ISO国家代码 修饰符来修饰。

Android将设备屏幕归类为两种常规属性:尺寸和分辨率。

为不同的屏幕尺寸, 创建不同的layout。

Android 3.2和以上版本支持定义屏幕尺寸的高级方法,它允许你根据屏幕最小长度和宽度,为各种屏幕尺寸指定与密度无关的资源。

为不同的屏幕分辨率,创建不同的bitmap,更多信息参考 Iconography design

Platform Versions 的控制面板会定时更新,通过统计访问Google Play Store的设备数量,来显示运行每个版本的安卓设备的分布。

为了能在几个Android版本中都能提供最好的特性和功能,你应该在你的app中使用Android Support Library,它能使你的app能在旧平台上使用最近的几个平台的APIs。

<uses-sdk>元素中的minSdkVersion和targetSdkVersion 属性,标明在设计和测试app时,最低兼容API的级别和最高适用的API级别。

非核心功能,在运行时检查系统版本,决定是否支持该功能。

当解析layout XML资源时,Android会忽略当前设备不支持的XML属性。所以你可以安全地使用较新版本的XML属性,而不需要担心旧版本Android遇到这些代码时会崩溃。

通过使用内置的风格和主题,你的app自然地随着Android新版本的发布,自动适配最新的外观和体验。

4.管理Activity的生命周期(Managing the Activity Lifecycle)

当用户进入,退出,回到你的App,在程序中的Activity 实例都经历了生命周期中的不同状态。在生命周期的回调方法里面,你可以声明当用户离开或者重新进入这个Activity所需要执行的操作。
Activity生命周期的每一个阶段就像金字塔中的台阶。当系统创建了一个新的activity实例,每一个回调函数会向上一阶的移动activity状态。金字塔顶端意味着activity是跑在最前端的并且用户可以与它进行交互。当用户开始离开这个activity,为了卸载这个activity,系统会调用其它方法来向下一阶移动activity状态。在某些情况下,activity会隐藏在金字塔下等待(例如当用户切换到其他app),这个时候activity可以重新回到顶端(如果用户回到这个activity)并且恢复用户离开时的状态。
确保你的app能够像用户期望的那样执行, 如何实现一个符合用户期待的app,你需要注意下面几点:
当使用你的app的时候,不会因为有来电通话或者切换到其他app而导致程序crash。
当用户没有激活某个组件的时候不要消耗宝贵的系统资源。
当离开你的app并且一段时间后返回,不要丢失用户的使用进度。
当设备发送屏幕旋转的时候,不会crash或者丢失用户的使用进度。
在上图所示的几个生命状态中只有三个状态是静态的,这三个状态下activity可以存在一段比较长的时间。(其它几个状态会很快就切换掉,停留的时间比较短暂)。
Activity 响应用户行为的单元
为了建立一个activity所需要的一些基础操作需要重写 onCreate() 方法。如,声明UI元素 ,定义成员变量,配置UI等。(onCreate 里面尽量少做事情,避免程序启动太久都看不到界面)。
当你的activity进入paused状态,系统会调用你的activity中的onPause()方法, 在这个方法里面可以允许你执行停止目前正在运行任务的操作,比如暂停视频播放或者是保存那些有可能需要长期保存的信息。如果用户从暂停状态回到你的activity,系统应该恢复那些数据并执行onResume()方法。
当系统调用你的activity中的onPause(),从技术上讲,那意味着你的activity仍然处于部分可见的状态,但大多数时候,那意味着用户正在离开这个activity并马上会进入Stopped state. 你通常应该在onPause()回调方法里面做下面的事情:
停止动画或者是其他正在运行的操作,那些都会导致CPU的浪费.
提交没有保存的改变,但是仅仅是在用户离开时期待保存的内容(例如邮件草稿).
释放系统资源,例如broadcast receivers, sensors (比如GPS), 或者是其他任何会影响到电量的资源。
例如, 如果你的程序使用Camera,onPause()会是一个比较好的地方去做那些释放资源的操作。你应该避免在onPause()时执行CPU-intensive 的工作,例如写数据到DB,因为它会导致切换到下一个activity变得缓慢(你应该把那些heavy-load的工作放到onStop()去做)。
系统每次调用 onResume 这个方法时,activity都处于最前台,包括第一次创建的时候。所以,你应该实现onResume()来初始化那些你在onPause方法里面释放掉的组件,并执行那些activity每次进入Resumed state都需要的初始化动作 (例如开始动画与初始化那些只有在获取用户焦点时才需要的组件)。
当你的activity调用onStop()方法, activity不再可见,并且应该释放那些不再需要的所有资源。一旦你的activity停止了,系统会在不再需要这个activity时摧毁它的实例(和栈结构有关,通常back操作会导致前一个activity被销毁)。在极端情况下,系统会直接杀死你的app进程,并且不执行activity的onDestroy()回调方法, 因此你需要使用onStop()来释放资源,从而避免内存泄漏。(这点需要注意)。
当你的activity已经停止,Activity对象会保存在内存中,并且在activity resume的时候重新被调用到。你不需要在恢复到Resumed state状态前重新初始化那些被保存在内存中的组件。系统同样保存了每一个在布局中的视图的当前状态,如果用户在EditText组件中输入了text,它会被保存,因此不需要保存与恢复它。即使系统会在activity stop的时候销毁这个activity,它仍然会保存View对象的状态(比如EditText中的文字) 到一个Bundle中,并且在用户返回这个activity时恢复他们(下一个会介绍在activity销毁与重新建立时如何使用Bundle来保存其他数据的状态)。

5.使用Fragment建立动态UI

为了在Android上创建动态的、多窗口的用户交互体验,你需要将UI组件和Activity操作封装成模块进行使用,在activity中你可以对这些模块进行切入切出操作。你可以用Fragment来创建这些模块,Fragment就像一个嵌套的activity,拥有自己的布局(layout)以及管理自己的生命周期。用fragment来可以创建动态的用户体检,以及在不同屏幕尺寸的设备上优化你的APP的用户体验。这个地方的动态是指,一个
Activity 中的 view 可以拆分组合成为模块动态的切换,这个功能也可以使用 viewGroup 实现,只是没有使用 fragment 这样方便,也没有模块的生命周期和后退栈的控制,并且把 controller 中的功能放到 view 中从MVC分层上来说也不太合适。Activity 被 Fragment 分成模块以后,Activity 就只需要管理 Fragment 就行了,fragment 的 添加 替换 移除 和 fragment 之间的通信。
和 Fragment 使用相关的类和方法有:
FragmentActivity
      getFragmentManager
FragmentManger
      beginTransaction
FragmentTransaction
      add
      replace
      remove
      addToBackStack
      commit
Fragment
      onCreateView
问题:
怎么理解 Activity 和 Fragment 之间生命周期函数调用的先后关系?
fragment 是 Activity 中的元素,是嵌套的 Activity,所以按道理在创建过程中所有 fragment 中的生命周期函数应该先于 Activity 调用,而在销毁过程中 Activity 应该应该先于 Fragment 调用。一般来说,动态替换的 fragment 都是在 Activity 处于 Resumed 状态后才会调用 replace 方法动态替换 Fragment。因为使用 Fragment 的时候,Activity 和 Fragment 的功能不同,所以Acvitity
和 Fragment 的生命周期的先后关系其实不用关心。
fragment 生命周期日志如下,说明 :
1.fragment 的 oncreate 在 oncreateview 之前,这个可以理解,和 activity 一样,其实是在 activity 的 oncreate 函数中调用的 addContentView。
2.fragment 中 oncreate 是在 fragmentManager.addfragment 之后,才重新使用新的 handler 处理周期调用的。
3.fragment 中 onStart 在 Activity.onStart 之前,这个可以理解为,Activity 中包含多个 Fragment,Activity 要显示出来,必须里面的 Fragment 先显示出来。
4.fragment 中的 onResume 在 Activity.onResume 之后,这个可以理解为,Activity 中包含多个 Fragment,Fragment 要能获取输入分发,必须 Activity 先能处理输入分发。
5.fragment 中的 onPause onStop onDestory 都在 Activity 之前,这个可以理解为,a.这个过程和创建的过程是相逆的,b.Activity 要后于 Activity 中的元素销毁。
6.oncreateView 相当于 actvity 中的 addContentView。
所有fragment之间的交互需要通过他们关联的activity,两个fragment之间不应该直接交互。

6.数据保存(Saving Data)

如果你有一个相对较小的key-value集合需要保存,你应该使用SharedPreferences APIs。 
File 对象非常适合用来读写那种流式顺序的数据。
所有的Android设备都有两个文件存储区域:"internal" 与 "external" 存储。 那两个名称来自与早先的Android系统中,那个时候大多数的设备都内置了不可变的内存(internal storage),然后再加上一个类似SD card(external storage)这样可以卸载的存储部件。后来有一些设备把"internal" 与 "external" 的部分都做成不可卸载的内置存储了,虽然如此,但是这一整块还是从逻辑上有被划分为"internal"与"external"的。
Internal storage:
总是可用的
这里的文件默认是只能被你的app所访问的。
当用户卸载你的app的时候,系统会把internal里面的相关文件都清除干净。
Internal是在你想确保不被用户与其他app所访问的最佳存储区域。
External storage:
并不总是可用的,因为用户可以选择把这部分作为USB存储模式,这样就不可以访问了。
是大家都可以访问的,因此保存到这里的文件是失去访问控制权限的。
当用户卸载你的app时,系统仅仅会删除external根目录(getExternalFilesDir())下的相关文件。
External是在你不需要严格的访问权限并且你希望这些文件能够被其他app所共享或者是允许用户通过电脑访问时的最佳存储区域。
目前,所有的apps都可以在不指定某个专门的权限下做读external storage的动作。但是,这在以后的版本中会有所改变。如果你的app只需要读的权限(不是写), 那么你将需要声明 READ_EXTERNAL_STORAGE 权限。为了确保你的app能持续地正常工作,你需要现在就声明读权限。,如果你的程序有声明读的权限,那么就默认有了写的权限。
因为external storage可能是不可用的比如SD卡被拔出,那么你应该在访问之前去检查是否可用。
系统并不能保证你可以写入通过getFreeSpace()查询到的容量文件。
对于重复或者结构化的数据(如联系人信息)等保存到DB是个不错的主意。

7.与其他应用的交互(Interacting with Other Apps)

当你想要叫起不同的app来执行那个动作,则必须使用隐式(implicit)的intent,Implicit intents并不会声明需要启动的组件的类名,它使用的是声明一个需要执行的动作。action指定了你想做的事情。

隐式 intent 4 元素:action data type extra数据

intent 的 setdata 方法可以设置 uri, 默认的,系统会根据Uri数据类型来决定需要哪些合适的MIME type。如果你没有在intent中包含一个Uri, 则通常需要使用 setType() 方法来指定 intent 附带的数据类型。设置 MIME type 是为了指定哪些 activity 可以应该接受这个 intent


如果你触发了一个intent,而且没有任何一个app会去接收这个intent,那么你的app会crash。

IntentFilter 3 元素:
Action:一个想要执行的动作的名称。通常是系统已经定义好的值,例如ACTION_SEND或者ACTION_VIEW。 在intent filt中用<action>指定它的值,值的类型必须为字符串,而不是API中的常量(看下面的例子)
Data:Intent附带数据的描述。在intent filt中用<data>指定它的值,可以使用一个或者多个属性,你可以只定义MIME type或者是只指定URI prefix,也可以只定义一个URI scheme,或者是他们综合使用。 如果你不想handle Uri 类型的数据,那么你应该指定 android:mimeType 属性。例如 text/plain or image/jpeg.

Category:提供一个附加的方法来标识这个activity能够handle的intent。通常与用户的手势或者是启动位置有关。系统有支持几种不同的categories,但是大多数都不怎么用的到。而且,所有的implicit intents都默认是 CATEGORY_DEFAULT 类型的。在intent filt中用<category>指定它的值。

抱歉!评论已关闭.