android学习笔记
(转自http://blog.csdn.net/eddyx/article/details/7236646)
年前开始,转向安卓平台的开发了,大方向是在安卓平台上用c++开发功能库,供安卓NDK及更上层平台调用。起点挺高,基础较低,从安卓基本概念看起。
把刚读过的《疯狂Android讲义》做些笔记,以利于掌握知识点,进而可以动手开发。
安卓的基本组件分为Activity,View,Service,BroadcastReceiver,ContentProvider以及Intent和IntentFilter。
- Activity是安卓应用中负责和用户交互的组件,相当于swing编程中的JFrame控件。
- View组件是所有UI控件,容器控件的基类,是用户实实在在看到的部分。通过Activity的setContentView()将指定的View显示出来。
- Service地位和Activity并列,Service运行于后台,不和用户交互,没有图形界面。
- BroadcastReceiver负责监听安卓应用中其他组件的事件。
- ContentProvider,多个应用程序间进行实时数据交换,安卓提供了数据交换的标准。结合ContentResolver来访问数据。
- Intent和IntentFilter,它是安卓应用内不同组件间通信的载体。Activity, Service, BroadcasetReceiver三种组件之间的通信都以Intent为载体。
接下来,按照上面的顺序,粗略的记录个组件的要点。
Activity:
安卓应用要求所有应用程序组件必须显示配置。
配置好后,使用startActivity(Intent intent) 启动其他Activity,或者使用startActivityForResult(Intent intent, int requestCode), 以指定请求码启动新的Activity,并且等待其启动结果。
对于Activity返回的结果,需要重写onActivityResult(int requestCode, int resultCode, Intent intent),来处理返回的结果。
关闭Activity使用finish()或是finisheActivity(int requestCode)来关闭。
Activity之间可以传递数据,可以将数据放入Intent即可,方法如下, putExtras(Bundle data), Bundle是简单的数据包,可以用putXxx(String key, Xxx data), 向Bundle放入各种类型的数据,也可以使用putSerializable(String key, Serializable data), 来放入可序列化对象。取出数据使用getExtras(), 从Bundle中取出数据使用getXxx(String key)或者getSerializable(String key)。
Activity的生命周期有四个状态,活动,暂停,停止,销毁。对应生命周期有如下方法会被系统回调。 onCreate(Bundle saveStatus), onStart(), onRestart(), onResume(), onPause, onStop, onDestroy()。
Intent和IntentFilter:
Intent对象大致包含Component, Action, Category, Data, Type, Extra和 Flag。
Component用于明确指定需要启动的目标组件。有如下几个构造器ComponentName(String pkg, String cls), ComponentName(Context pkg, String cls), ComponentName(Context pkg, Class<?> cls)。使用这种方式启动组件时,不需要配置<intent-filter>元素。
Action, Category属性,Action属性指明一个抽象的动作,由配置中的<intent-filert>决定。可以包含多个Action,表示可以响应多种Intent。一个Intent只能有一个Action,但可以包含多个Category。
安卓系统提供了大量的系统Activity通过指定Action,Category来调用。
Data,Type属性,Data属性用于向Action属性提供操作的数据,接受Uri对象,如content://com.android.contacts/contacts/1。当Intent不指定Data数据类型时Type属性才会起作用,否则安卓系统会分析数据类型,一般用不到。
Extra属性就是负责在多个Action之间进行数据交换,前面已经介绍过。
ContentProvider:
安卓提供了ContentProvider用作不同应用程序之间进行数据交换。
定义自己的ContentProvider类需要继承安卓提供的基类,然后在AndroidManifest.xml文件中注册, 注册时指定authorities属性,类似于指定一个地址或域名,其他程序就可以通过地址来访问数据了。
继承基类之后,还需要提供CRUD方法,以供调用时进行相应操作。
public boolean onCreate(), public Uri insert(Uri uri, ContentValues values), public int delete(Uri uri, String[] selectionArgs), public in update(Uri uri, ContentValues values, String selection, String[] selectionArgs, String sortOrder), public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder), public String getType(Uri uri)
ContentProvider以单例模式运行。
Context提供用getContentResolver()来获取ContentResolver对象,用insert,delete,update,query来操作数据。
具体开发时还要用到UriMatcher工具类,这个工具类提供了两个方法,void add(URI(String authority, String path, int code)用注册Uri,其中authority和path构成Uri,code表示Uri对应的标识码。int match(Uri uri),用来判断指定Uri对应的标识码。
ContentObserver是用于监听ContentProvider的数据改变,需要继承基类并重写onChange(boolean selfChange)方法,再通过ContentResolver向指定Uri注册监听器。registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer)。
Service:
Service与Activity类似,开发需要两个步骤,继承Service的子类,在文件中配置改Service。
Service中的生命周期方法如下,abstract IBinder onBind(Intent intent), 该方法子类必须实现,返回IBinder对象,可通过该对象与Service组件通信。 void onCreate(), void onDestroy(), void onStartCommand(Intent intent, int flags, int startId), boolean onUnbind(Intent intent)。
Service的调用方式有两种,通过Context的startService()方法,调用者和service没有关联,调用者退出,service继续运行。通过Context的bindService()方法,调用者和service绑在一起,调用者退出,service也终止。
具体参数如下,bindService(Intent service ServiceConnection conn, int flags),ServiceConnection用于监听访问者与Service之间的连接情况,连接成功将回调onServiceConnected(ComponentName name, IBinder service),这个IBinder可实现与Service之间的通信。实际开发时需要实现自己的IBinder对象,断开时将回调onServiceDisconnected(ComponentName name),flags表示绑定时是否自动创建Service。
各进程之间一般无法进行数据交换,所以需要通过远程调用接口。与本地调用Service类似,远程Service将IBinder对象的代理传给客户端的onServiceConnected方法的第二个参数。
需要使用AIDL接口定义语言定义通信接口,语法非常简单。定义接口的源代码必须以aidl结尾。接口中用的数据类型除基本类型,String, List, Map, CharSequence外,都要导包。定义好接口之后,ADT工具会自动生成一个java接口,接口里含有一个Stub内部类,该类实现了IBinder和定义的接口。
客户端首先要将AIDL接口文件拷贝到客户端应用中,客户端创建ServiceConnection对象,以生成的对象做参数,调用bindService()方法绑定远程Service。使用asInterface(service)方法获得对象代理。
如果传输的数据是自定义类型,安卓要求调用远程Service的参数和返回值都必须实现Parcelable接口。并用AIDL代码定义这些自定义类型。
BroadcastReceiver:
这是一种全局监听器,非常方便地实现系统中不同组件之间的通信。
调用需要两步,创建需要启动的BroadcastReceiver的Intent。调用Context的sendBroadcast()或sendOrderedBroadcast()方法来启动指定的BroadcastReceiver.
onReceive()方法如果不能在10秒钟内完成操作,会弹出Application No Response的对话框,所以,如果有耗时的操作,最好启动Service来完成。
普通的Broadcast是异步的,几乎所有接收者在同时接到消息,但无法一个接一个传递,也无法终止。Ordered Broadcast可按优先级别依次传递。优先级别在<intent-filter.../>元素的android:priority属性中定义,值越大优先级越高。接收者也可终止传播。Ordered Broadcast接收者可以将数据传递给下一个接收者,setResultExtras(Bundle)方法将处理结果存入Broadcast中,下一个接收者可通过getREsultExtras(true)来获取。
图形界面的事件处理:
安卓系统提供了两种方式的事件处理,基于回调的事件处理和基于监听器的事件处理。监听的做法就是为界面组件绑定特定事件监听器,回调就是重写组件特定的回调方法或重写Activity的回调方法。
监听器通常有如下几种形式,内部类,外部类,Activity本身作为监听器,匿名内部类。内部类比较常用,可以自由访问外部类的组件。
回调机制的意思就是在GUI组件上激发某事件时,组件自己特定的方法将负责处理该事件。一般只能继承该GUI组件,重写该类的时间处理方法来实现。回调事件一般会返回boolean类型的值,如果是true该事件不会传播出去,如果是false,则会传播出去。
监听与回调的顺序是,先触发监听器后调用回调方法。
安卓平台不允许Activity新启动的线程访问该Activity里的界面组件,这需要通过Handlerler的消息传递机制来解决。Handler类的主要作用有两个,一是在新启动线程中发送消息,二是在主线程中获取,处理消息。为了主线程适时处理消息,开发者需要重写Handler类中处理消息的方法。