转载处:http://blog.csdn.net/fangxinglian/article/details/22981277


程序入口点



类似于win32程序里的WinMain函数,Android自然也有它的程序入口点。它通过在AndroidManifest.xml文件中配置来指明,可以看到名为NotesListactivity节点下有这样一个intent-filter,actionandroid.intent.action.MAIN,
Category指定为android.intent.category.LAUNCHER,这就指明了这个activity是作为入口activity,系统查找到它后,就会创建这个activity实例来运行,若未发现就不启动(你可以把MAIN改名字试试)


<intent-filter>
<actionandroid:name="android.intent.action.MAIN"
/>
<categoryandroid:name="android.intent.category.LAUNCHER"
/>
</intent-filter>

NotesList详解


就从入口点所在的activity(见图1)开始,可以看到这个activity最重要的功能就是显示日志列表。这个程序的日志都存放在Sqlite数据库中,因此需要读取出所有的日志记录并显示。

先来看两个重要的私有数据,第一个PROJECTION字段指明了日志列表所关注的数据库中的字段(即只需要IDTitle就可以了)。

privatestaticfinalString[] PROJECTION=newString[] {
Notes._ID,
//0
Notes.TITLE,//1
};


第二个字段COLUMN_INDEX_TITLE指明title字段在数据表中的索引。
privatestaticfinalintCOLUMN_INDEX_TITLE=1;
然后就进入第一个调用的函数onCreate
Intent intent=getIntent();
if(intent.getData()==null)
{
intent.setData(Notes.CONTENT_URI);
}

因为NotesList这个activity是系统调用的,此时的intent是不带数据和操作类型的,系统只是在其中指明了目标组件是Notelist,所以这里把”content:// com.google.provider.NotePad/notes”保存到intent里面,这个URI地址指明了数据库中的数据表名(参见以后的NotePadProvider类),也就是保存日志的数据表notes
Cursor cursor=managedQuery(getIntent().getData(), PROJECTION,null,null, Notes.DEFAULT_SORT_ORDER);
然后调用managedQuery函数查询出所有的日志信息,这里第一个参数就是上面设置的” content:// com.google.provider.NotePad/notes”这个URI,即notes数据表。PROJECTION字段指明了结果中所需要的字段,Notes.DEFAULT_SORT_ORDER指明了结果的排序规则。实际上managedQuery并没有直接去查询数据库,而是通过Content Provider来完成实际的数据库操作,这样就实现了逻辑层和数据库层的分离。
SimpleCursorAdapter adapter=newSimpleCursorAdapter(this, R.layout.noteslist_item, cursor,newString[] { Notes.TITLE },newint[] { android.R.id.text1 });
setListAdapter(adapter);

查询出日志列表后,构造一个CursorAdapter,并将其作为List View的数据源,从而在界面上显示出日志列表。可以看到,第二个参数是R.layout.noteslist_item,打开对应的noteslist_item.xml文件,
<TextViewxmlns:android="http://schemas.android.com/apk/res/android"
android:id
="@android:id/text1"
android:layout_width
="fill_parent"
android:layout_height
="?android:attr/listPreferredItemHeight"
android:textAppearance
="?android:attr/textAppearanceLarge"
android:gravity
="center_vertical"
android:paddingLeft
="5dip"
android:singleLine
="true"
/>

就是用来显示一条日志记录的TextView,最后两个字段指明了实际的字段映射关系,通过这个TextView来显示一条日志记录的title字段。

处理选择日志事件

既然有了日志列表,就自然要考虑如何处理某一条日志的单击事件,这通过重载onListItemClick方法来完成,
@Override
protectedvoidonListItemClick(ListView l, View v,intposition,longid) {
Uri uri
=ContentUris.withAppendedId(getIntent().getData(), id);

String action
=getIntent().getAction();
if(Intent.ACTION_PICK.equals(action)||Intent.ACTION_GET_CONTENT.equals(action)) {
//The caller is waiting for us to return a note selected by
//the user.The have clicked on one, so return it now.
setResult(RESULT_OK,newIntent().setData(uri));
}
else{
//Launch activity to view/edit the currently selected item
startActivity(newIntent(Intent.ACTION_EDIT, uri));
}
}

首先通过”content:// com.google.provider.NotePad/notes”和日志的id号拼接得到选中日志的真正URI,然后创建一个新的Intent,其操作类型为Intent.ACTION_EDIT,数据域指出待编辑的日志URI(这里只分析else块)。

Intent深度剖析

那么,上面这句startActivity(newIntent(Intent.ACTION_EDIT, uri))执行后会发生什么事情呢?这时候Android系统就跳出来接管了,它会根据intent中的信息找到对应的activity,在这里找到的是NoteEditor这个activity,然后创建这个activity的实例并运行。

那么,Android又是如何找到NoteEditor这个对应的activity的呢?这就是intent发挥作用的时刻了。

new Intent(Intent.ACTION_EDIT, uri)

这里的Intent.ACTION_EDIT=” android.intent.action.EDIT”,另外通过设置断点,我们看下这里的uri值:



可以看到选中的日志条目的URI是:content://com.google.provider.NotePad/notes/1

然后我们再来看下 Androidmanfest.xml, 其中有这个 provider
< provider android:name ="NotePadProvider"
android:authorities
="com.google.provider.NotePad"
/>

发现没有?它也有 com.google.provider.NotePad ,这个是 content://com.google.provider.NotePad/notes/1 的一部分,同时

< activity android:name ="NoteEditor"
android:theme
="@android:style/Theme.Light"
android:label
="@string/title_note"
android:screenOrientation
="sensor"
android:configChanges
="keyboardHidden|orientation"
>
<!-- This filter says that we can view or edit the data of
a single note
-->
< intent-filter android:label ="@string/resolve_edit" >
< action android:name ="android.intent.action.VIEW"
/>
< action android:name ="android.intent.action.EDIT"
/>
< action android:name ="com.android.notepad.action.EDIT_NOTE"
/>
< category android:name ="android.intent.category.DEFAULT"
/>
< data android:mimeType ="vnd.android.cursor.item/vnd.google.note"
/>
</ intent-filter >
<!-- This filter says that we can create a new note inside
of a directory of notes.
-->
< intent-filter >
< action android:name ="android.intent.action.INSERT"
/>
< category android:name ="android.intent.category.DEFAULT"
/>
< data android:mimeType ="vnd.android.cursor.dir/vnd.google.note"
/>
</ intent-filter >
</ activity >

上面第一个 intent-filter 中有一个 action 名为 android.intent.action.EDIT ,而前面我们创建的 Intent 也正好是

Intent.ACTION_EDIT=” android.intent.action.EDIT”,想必大家已经明白是怎么回事了吧。

下面就进入 activity 选择机制了:
系统从 intent 中获取道 uri ,得到了 content://com.google.provider.NotePad/notes/1, 去掉开始的 content: 标识,得到 com.google.provider.NotePad/notes/1, 然后获取前面的 com.google.provider.NotePad ,然后就到 Androidmanfest.xml 中找到 authorities com.google.provider.NotePad provider ,这个就是后面要讲的 contentprovider, 然后就加载这个 content provider

< provider android:name ="NotePadProvider"
android:authorities
="com.google.provider.NotePad"
/>

在这里是 NotePadProvider, 然后调用 NotePadProvider gettype 函数,并把上述 URI 传给这个函数,函数返回 URI 所对应的类型(这里返回 Notes.CONTENT_ITEM_TYPE ,代表一条日志记录,而 CONTENT_ITEM_TYPE = " vnd.android.cursor.item/vnd.google.note " )。
@Override
public String getType(Uri uri) {
switch (sUriMatcher.match(uri)) {
case NOTES:
return Notes.CONTENT_TYPE;
case NOTE_ID:
return Notes.CONTENT_ITEM_TYPE;
default :
throw
new IllegalArgumentException( " Unknown URI "
+ uri);
}
}

上面的 sUriMatcher.match 是用来检测 uri 是否能够被处理,而 sUriMatcher .match(uri) 返回值其实是由
sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sUriMatcher.addURI(NotePad.AUTHORITY,
" notes " , NOTES);
sUriMatcher.addURI(NotePad.AUTHORITY,
" notes/# " , NOTE_ID);

决定的。

然后系统使用获得的" vnd.android.cursor.item/vnd.google.note "”android.intent.action.EDIT”androidmanfest.xml中去找匹配的activity.


< intent-filter android:label ="@string/resolve_edit" >
< action android:name ="android.intent.action.VIEW"
/>
< action android:name ="android.intent.action.EDIT"
/>
< action android:name ="com.android.notepad.action.EDIT_NOTE"
/>
< category android:name ="android.intent.category.DEFAULT"
/>
< data android:mimeType ="vnd.android.cursor.item/vnd.google.note"
/>
</ intent-filter >

正好 NoteEditor 这个 activity intent-filter 满足上述条件 , 这样就找到了 NoteEditor 。于是系统加载这个类并实例化,运行,然后就到了 NoteEditor OnCreate 函数中(见后续文章)。

更多相关文章

  1. Android学习:LogCat日志查询
  2. Android(安卓)日志级别总结
  3. 获取Android手机上的图片和视频缩略图
  4. python logging 模块(一)
  5. Android中的自定义注解
  6. android:The application has stopped unexpectedly, please try
  7. Android(安卓)studio 分渠道打包,引用不同的moudle
  8. 日志工具类
  9. (未解决)问题记录ionic android 签名之后安装到手机上点击运行出

随机推荐

  1. mysql 获取今天、昨天0点时间戳的实例
  2. 详解MySQL中default的使用
  3. mysql中数据统计的技巧备忘录
  4. MySQL绿色解压缩版安装与配置操作步骤
  5. Mysql排序获取排名的实例代码
  6. mysql下centos安装mariadb的方法及遇到的
  7. Ubuntu 18.04下mysql 8.0 安装配置方法图
  8. mysql 8.0.11 压缩包版安装配置方法图文
  9. MySQL Community Server 8.0.11安装配置
  10. mysql8.0.11客户端无法登陆的解决方法