4种状态、7个重要方法和3个嵌套循环
活动(Active/Running)状态:当Activity运行在屏幕前台(处于当前任务活动栈的最上面),此时它获取了焦点能响应用户的操作,属于运行状态,同一个时刻只会有一个Activity 处于活动状态。
暂停(Paused)状态:当Activity失去焦点但仍对用户可见(如在它之上有另一个透明的Activity或Toast、AlertDialog等弹出窗口时)它处于暂停状态。暂停的Activity仍然是存活状态(它保留着所有的状态和成员信息并保持和窗口管理器的连接),但是当系统内存极小时可以被系统杀掉。
停止(Stopped)状态:完全被另一个Activity遮挡时处于停止状态,它仍然保留着所有的状态和成员信息。只是对用户不可见,当其他地方需要内存时它往往被系统杀掉。
非活动(Dead)状态:Activity尚未被启动、已经被手动终止,或已经被系统回收时处于非活动的状态,要手动终止Activity,可以在程序中调用"finish"方法。
onCreate:当Activity第一次被实例化的时候系统会调用,整个生命周期只调用1次这个方法。
onStart():当Activity可见未获得用户焦点不能交互时系统会调用。
onResume():当Activity可见且获得用户焦点能交互时系统会调用。
onRestart():当Activity已经停止然后重新被启动时系统会调用。
onPause():当系统启动另外一个新的Activity时,在新Activity启动之前被系统调用保存现有的Activity中的持久数据,而onSaveInstanceState()来记录activity的临时状态。
onStop():当Activity被新的Activity完全覆盖不可见时被系统调用。
onDestroy():当Activity(用户调用finish()或系统由于内存不足)被系统销毁杀掉时系统调用,(整个生命周期只调用1次)用来释放onCreate ()方法中创建的资源,如结束线程等。
Activity完整的生命周期:从第一次调用onCreate()开始直到调用onDestroy()结束。
Activity的可视生命周期:从调用onStart()到相应的调用onStop()。在这两个方法之间,可以保持显示Activity所需要的资源。如在onStart()中注册一个广播接收者监听影响你的UI的改变,在onStop() 中注销。
Activity的前台生命周期:从调用onResume()到相应的调用onPause()。
二.常见的widget
TextView、EditText、Button、ImageView,功能分视图和事件
三.Fragment
Android是在Android 3.0开始引入Fragment的。我们可以把Fragment想成Activity中的模块,这个模块有自己的布局,有自己的生命周期,单独处理自己的输入,在Activity运行的时候可以加载或者移除Fragment模块,并且可以在多个Activity中复用。
因为Fragment必须嵌入在Acitivity中使用,所以Fragment的生命周期和它所在的Activity是密切相关的。如果Activity是暂停状态,其中所有的Fragment都是暂停状态;如果Activity是stopped状态,这个Activity中所有的Fragment都不能被启动;如果Activity被销毁,那么它其中的所有Fragment都会被销毁。
但是,当Activity在活动状态,可以独立控制Fragment的状态,比如加上或者移除Fragment。
onAttach()->onCreate()->onCreateView()->onActivityCreated->onStart->onResume()->active->onPause()->onStop()->onDestroyView()->onDestroy()->onDetach()
需要重写的3个方法:
onCreate():系统在创建Fragment的时候调用这个方法,这里应该初始化相关的组件,一些即便是被暂停或者被停止时依然需要保留的东西。
onCreateView():当第一次绘制Fragment的UI时系统调用这个方法,必须返回一个View,如果Fragment不提供UI也可以返回null。注意,如果继承自ListFragment,onCreateView()默认的实现会返回一个ListView,所以不用自己实现。
onPause():当用户离开Fragment时第一个调用这个方法,需要提交一些变化,因为用户很可能不再返回来。
Fragment加入Activity的2种方式:
在布局文件中使用标签<fragment>添加;
通过编程的方式将Fragment加入到一个ViewGroup中,首先,需要一个FragmentTransaction实例,之后,用add()方法在父控件中加上Fragment的对象,通过commit()方法使得FragmentTransaction实例的改变生效。
四.ActionBar
Android是在Android 3.0开始引入ActionBar的。取代3.0之前的标题栏,并提供更为丰富的导航效果。
主要功能包含:
1. 显示选项菜单。
2. 提供标签页的切换方式的导航功能,可以切换多个fragment。
3. 使用程序的图标作为返回Home主屏或向上的导航操作。
获取:actionBar = this.getActionBar()
隐藏:在manifest.xml中将主题设置为Theme.Holo.NoActionBar为一个Activity去除掉ActionBar。或者调用show()或者hide()方法来相应的显示或者隐藏ActionBar。
添加Item:
(1)通过程序动态添加,重写onCreateOptionsMenu方法,以MenuItem为对象,通过setShowAsAction方法绑定到Bar上。
(2)通过Menu.xml文件布局,重写onCreateOptionsMenu方法,以MenuInflater的方式将布局填充到Bar上。
使用带字的ActionItem:(1)Action item 默认格式是如果菜单项含字和图标的话,只显示图标
(2)如果想要显示字的效果,在xml里如下设置:android:showAsAction="ifRoom|withText" 或者在代码里调用setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
ActionBar的单击事件:ActionItem的触发与以前版本中的活动菜单回调方法onOptionsItemSelected()一致。
图标:默认图标在ActionBar的左侧,当用户点击图标时,系统会调用你的Activity里面的onOptionsItemSelected() 方法里面的Android.R.id.Home里定义的事件。我们可以重写这个方法,添加一个条件执行该行为:让它跳转到这个应用的主Activity而不是返回的主屏幕。如果选择返回应用的主activity,最好的方式是在创建的Intent中添加FLAG_ACTIVITY_CLEAR_TOP这个标签,表示如果应用的主Activity已经在activity栈中存在,所有在其上的activity都会被销毁,然后主activity会到栈顶,而不用创建主Activity的的新实例。当我们想实现用户点击图标后返回前一个activity,可以通过在Actionbar设置setDisplayHomeAsUpEnabled(true) 来实现。
添加视图:我们可以在Menu.xml中的Item项中的android:actionLayout属性来指定我们希望现实布局资源的ID,来实现定制的视图。主要的Item类别和属性如下:
1).搜索栏:android:actionLayout="@layout/collapsibleview"
2).普通类型(带图片带文字):android:showAsAction="ifRoom|withText"
3).分享类型:android:actionProviderClass="android.widget.ShareActionProvider"
4).可拓展类型:android:showAsAction="collapseActionView"
5).列表类型:再套一层<menu>标签
TAB标签栏:(1)设置为Tab模式:bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS).(2)构建对象ActionBar.Tab tabA = bar.newTab().setText("A Tab").(3)重写ActionBar.TabListener,监听控制Fragment切换.(4)addTab().
下拉标签栏:(1)设置为list模式:bar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST).(2)重写监听OnNavigationListener实现Fragemt的切换.(3)设置下拉菜单和监听器bar.setListNavigationCallbacks(adapter, listen);
ActionBar的美化:重写其style文件。
五.ListView
比较常用的组件,它以列表的形式展示具体内容,并且能够根据数据的长度滚动显示。
三元素:控件ListView,用来展示列表的View。适配器Adapter,用来把数据映射到ListView上。数据List<data>。
基本类型:ArrayAdapter,SimpleAdapter和SimpleCursorAdapter
自定义Adapter:继承BaseAdapter,重写四个主要方法。listView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到listView的长度,然后根据这个长度,调用getView()逐一绘制每一行,在这个函数里面首先获得一个View(这个看实际情况,如果是一个简单的显示则是View,如果是一个自定义的里面包含很多控件的时候它其实是一个ViewGroup),然后再实例化并设置各个组件及其数据内容并显示它。还有getItemId(int arg0)和getItem(int arg0)方法。
显示原理:
1.如果你有几千几万甚至更多的选项(item)时,其中只有可见的项目存在内存(我们所说的优化就是说在内存中的优化),其他的在Recycler中
2.ListView先请求一个type1视图(getView)然后请求其他可见的项目。convertView在getView中是空(null)的
3.当item1滚出屏幕,并且一个新的项目从屏幕低端上来时,ListView再请求一个type1视图。convertView此时不是空值了,它的值是item1。你只需设定新的数据然后返回convertView,不必重新创建一个视图。换句话说ListView仅仅缓存了可视范围内的View,随后的滚动都是对这些View进行数据更新
优化:
(1)使用空判断避免convertView的重复使用,使用ViewHolder缓存行中的View避免重复的findViewById
View view = convertView;
ViewHolder holder;
if(view==null){
view=LayoutInflater.from(context).inflate(R.layout.section_list_item1,null);
holder = new ViewHolder();
holder.tv_name=(TextView)view.findViewById(R.id.contact_contactinfoitem_tv_name);
view.setTag(holder);
} else {
holder = (ViewHolder)view.getTag();
}
(2)图片处理:用Option保存图片大小、不要直接加载图片到内存去;拿到的图片要经过边界压缩;在getView中做图片转换时,产生的中间变量一定及时释放。
(3)尽量避免在BaseAdapter中使用static来定义全局静态变量。
(4)Context尽量使用Application Context,因为Application的Context的生命周期比较长,引用它不会出现内存泄露的问题。
(5)尽量避免在ListView适配器中使用线程,因为线程产生内存泄露的主要原因在于线程生命周期的不可控制。
六、主要布局
LinearLayout,在一个方向上(垂直或水平)线性排列所有子元素
RelativeLayout,子元素是根据它们所设置的参照控件和参数进行相对布局,它的位置是相对其他子控件或者父控件的。
FrameLayout,添加到这个布局中的视图都以层叠的方式显示,第一个添加的控件被放在最底层
TableLayout,把子元素放入到行与列中
AbsoluteLayout,子控件根据指定横纵坐标值来布局
七、Animation
1.Tween Animation:通过对场景里的对象不断做图像变换(平移、缩放、旋转)产生动画效果,即是一种渐变动画;
2.Frame Animation:顺序播放事先做好的图片,是一种画面转换动画。
alpha 渐变透明度动画效果
scale 渐变尺寸伸缩动画效果
translate 画面转换位置移动动画效果
rotate 画面转移旋转动画效果
AnimationUtils.loadAnimation()加载,startAnimation执行
AnimationDrawable.start
八、Notification
类型:普通Notification:界面包含图标、标题、内容、时间、小图标、附加内容
大布局Notification:4.1之后引入的,在所有notification的最上面,中间多一块布局填充区域。又分NotificationCompat.InboxStyle类型、NotificationCompat.BigTextStyle类型、NotificationCompat.BigPictureStyle类型
自定义Notification:使用RemoteViews来填充布局。
步骤:(1)实例化NotificationManager负责Notification的“发出”与“取消”;
(2)创建Notification,并做设置
(3)创建一个Intent,该Intent使得当用户点击此Notification后触发的这个Intent
(4)实例化PendingIntent用来包装上述的Intent
(5)设置通知的标题和内容notification.setLatestEventInfo()
(6)发出通知:nManager.notify(ID, notification);
(7)取消通知:nManager.cancel(ID);
(8)填充自定义布局:RemoteViews remoteViews = new RemoteViews(getPackageName(),R.layout.custom_notification);
remoteViews.setOnClickPendingIntent(R.id.paly_pause_music,pendingIntent);
setContent(remoteViews);
九、Dialog
类型:确认类型对话框(2按钮、3按钮);输入框类型对话框;单选对话框;复选对话框;列表对话框;进度对话框;自定义对话框
创建:(1)创建AlertDialog.Builder;set属性;builder.create()生成Dialog;dialog.show();
(2)通过LayoutInflater生成View;通过buidler.setView设置布局;
(3)ProgressDialog.show();
十、Preference
类似Setting的界面布局结构。本质上与View相似,Preference的优点在于布局界面的可控性和高效率以及可存储值的简洁性(每个PreferenPreferencece存储在相对应下的SharedPreference文件夹下)。
类型: Preference:文本框;CheckBoxPreference:单选框;EditTextPreference:输入文本框;ListPreference:列表框;RingtonePreference铃声
相关类:PreferenceCategory :类似于LinearLayou、RelativeLayout,用于组合一组Preference,使布局更具备层次感;PreferenceScreen :所有Preference元素的根节点。
使用方法:Activity继承PreferenceActivity,然后在onCreate()方法中通过addPreferencesFromResource(R.xml.custom_preference)加载布局。
点击事件:在xml文件中配置<intent>节点;或者在编码中onPreferenceTreeClick()
十一、Drawable
类型:图片资源、StateListDrawable资源(selector):作为组件的背景或者前景Drawable资源时,可以随着组件状态的变更而自动切换相对应的资源、ShapeDrawable资源:绘制一个特定的形状,包括形状,阴影,圆角、ClipDrawable:裁剪一个其他资源;AnimationDrawable:动画;LayerDrawable:用来管理多个drawable的数组层叠;TransitionDrawable:定义了一个drawable可用于两张图片形成一个渐变的过渡效果生成一个TransitionDrawable对象;Inset Drawable:定义了一个drawable,跟据指定的距离插入到另一个drawable.
十二、AIDL
android内部进程通信接口的描述语言,可以定义并实现进程通信。
步骤:(1)创建.aidl文件,是一个接口文件;(2)编译,生成AIDLService.java;(3)实现你定义aidl接口中的内部抽象类Stub;(4)绑定客户端
十三、Custom View
继承View,重写其中的构造器,使用LayoutInflater填充布局或者使用onDraw在画布上绘制View,调用onMeasure计算宽高。
如果自定义的View需要有自定义的属性,需要在values下建立attrs.xml。在其中定义你的属性。
优化:采用最合适的控件组合、对于复杂的UI,写一个自定义的ViewGroup类来统一布局;代码逻辑优化,减少不必要的调用和刷新;
十四、Binder
Android系统进程间通信方式。四个角色:Server,Client,ServiceManager(以后简称SMgr)以及Binder驱动。其中 Server,Client,SMgr运行于用户空间,驱动运行于内核空间
十五、Android系统的优缺点
安全和隐私、过分依赖开发商缺少标准配置 、版本过多,升级过快
十六、ADT
uiautomatorviewer、hierarchyviewer、DDMS
十七、onLayout与onMeasure
1.onMeasure属于View的方法,用来测量自己和内容的来确定宽度和高度
2.onLayout属于ViewGroup的方法,用来为当前ViewGroup的子元素分配位置和大小
3.设置background后,会重新调用onMeasure和onLayout
4.onMeasure → onLayout → DispatchDraw:onMeasure负责测量这个ViewGroup和子View的大小,onLayout负责设置子View的布局,DispatchDraw就是真正画上去了。
十八、Layout/Attribute/Resource
Layout:布局
widget:控件
Attribute:属性
Resource:资源
十九、Drawable
Boundary:边界
State:状态
Layer:层次
二十、Text
Android系统默认支持三种字体,分别为:“sans”, “serif”, “monospace",使用Android:typeface="sans"属性调用。
除此之外还可以使用其他字体文件(*.ttf),首先要将字体文件保存在assets/fonts/目录下,
使用Typeface typeFace =Typeface.createFromAsset(getAssets(),"fonts/HandmadeTypewriter.ttf");为textView设置字体setTypeface(typeFace);
二十一、Menu
菜单资源文件放在res/menu目录中。菜单资源文件使用<menu>标签作为根节点。除了<menu>标签外,还有另外两个标签用于设置菜单项和分组,这两个标签是<item>和<group>。
使用MenuInflate menuInflate = getMenuInflate();
menuInflate.inflate(R.menu.option_menu,menu);填充布局
onOptionsItemSelected(MenuItem item)响应的操作
自定义菜单:自定义布局;重写onMenuOpened(int featureId, Menu menu)方法,一定要return false,这里弹出自定义的窗体;
二十二、Accessibility
针对有些用户由于视力上,身体上,年龄上的问题致使他们不能看完整的屏幕或者使用触屏,也包括了无法很好接收到语音信息和提示的听力能力比较弱的用户。Android提供了Accessibility功能和服务帮助这些用户更加简单地操作设备,包括文字转语音(这个不支持中文),触觉反馈,手势操作,轨迹球和手柄操作。
AccessibilityService类:需要重写onAccessibilityEvent():通过这个函数可以接收系统发送来的AccessibilityEvent,接收来的AccessibilityEvent是经过过滤的,过滤是在配置工作时设置的;
需要建立一个AccessibilityServiceInfo对象,通过这个对象设置监听系统事件类型,服务的反馈类型(震动,语音,声音),事件时间间隔,你想要监听的包名(或者说是应用程序)。最后调用setServiceInfo()进行设置。
二十三、android Resources
Android资源文件。只要是和界面相关的,都可以用资源文件表示。
主要有:anim动画xml、drawable图片文件、layout布局、values(strings字符串、arrays数组文件、colors颜色文件、dimens尺寸文件、styles样式文件、attrs属性文件)、xml任意的XML文件、raw直接复制到设备中的原生文件、menu菜单文件。assets中保存的一般是原生文件(MP3、MP4、视频、html)
二十四、Theme/Style/Attribute
Theme和Style,将一些通用的属性提取出来,方便使用。都位于values文件夹下styles.xml下,格式相同。
Theme在AndroidManifest.xml中的Application节点或者Activity节点设置android:theme,或者在对应Activity中通过代码设置setTheme(),影响整个应用或者一个Activity.
Style一般是在布局中的View中设置。影响单个View,如EditText,TextView等等。
Style优先级高于Theme
Attribute属性:为单个View的属性值;一系列的Attribute提取出来便是一个style。
二十五、分辨率和机型适配
1.明确机型适配范围;
2.采用较大像素的图片,便于向低分辨率适配;
3.采用9.png图片;
4.必要时有多套切图和布局;
5.使用wight权重布局;
6.使用多套dimens
二十六、Multiple Language
尽量将文字存放在res/values/string.xml资源文件中,辅以不用的后缀values-en、values-ch
二十七、CTS
兼容性测试工具。当我们的产品开发出来,并定制了自己的Android系统后,必须要通过最新的CTS检测。通过了CTS验证并将测试报告提交给Google,才有可能获得Android的商标和享受Android Market的权限。 CTS是一款通过命令行操作的工具。目前CTS只能在Linux下测试。
二十八、TestCase
用来进行Android单元测试。
JUnit TestCase类继承自JUnit的TestCase,不可以使用Instrumentation框架。基类是AndroidTestCase。子类有:
(1)ApplicationTestCase——测试整个应用程序的类。它允许你注入一个模拟的Context到应用程序中,在应用程序启动之前初始化测试参数,并在应用程序结束之后销毁之前检查应用程序。
(2)ProviderTestCase2——测试单个ContentProvider的类。因为它要求使用MockContentResolver,并注入一个IsolatedContext,因此Provider的测试是与OS孤立的。
(3)ServiceTestCase——测试单个Service的类。你可以注入一个模拟的Context或模拟的Application(或者两者),或者让Android为你提供Context和MockApplication。
Instrumentation TestCase类,继承自JUnit TestCase类,并可以使用Instrumentation框架,用于测试Activity。基类是InstrumentationTestCase。子类有:
(1)ActivityTestCase——Activity测试类的基类。
(2)SingleLaunchActivityTestCase——测试单个Activity的类。它能触发一次setup()和tearDown(),而不是每个方法调用时都触发。如果你的测试方法都是针对同一个Activity的话,那就使用它吧。
(3)SyncBaseInstrumentation——测试Content Provider同步性的类。它使用Instrumentation在启动测试同步性之前取消已经存在的同步对象。
(4)ActivityUnitTestCase——对单个Activity进行单一测试的类。使用它,你可以注入模拟的Context或Application,或者两者。它用于对Activity进行单元测试。不同于其它的Instrumentation类,这个测试类不能注入模拟的Intent。
(5)ActivityInstrumentationTestCase2——在正常的系统环境中测试单个Activity的类。你不能注入一个模拟的Context,但你可以注入一个模拟的Intent。另外,你还可以在UI线程(应用程序的主线程)运行测试方法,并且可以给应用程序UI发送按键及触摸事件。