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


程序入口点

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

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

NotesList详解

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

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

private static final String[] PROJECTION =new String[] {
            Notes._ID, // 0
            Notes.TITLE, // 1
    };

第二个字段COLUMN_INDEX_TITLE指明title字段在数据表中的索引。
private static final int COLUMN_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 =new SimpleCursorAdapter(this, R.layout.noteslist_item, cursor,new String[] { Notes.TITLE }, new int[] { android.R.id.text1 });
        setListAdapter(adapter);

查询出日志列表后,构造一个CursorAdapter,并将其作为List View的数据源,从而在界面上显示出日志列表。可以看到,第二个参数是R.layout.noteslist_item,打开对应的noteslist_item.xml文件,
<TextView xmlns: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
    protected void onListItemClick(ListView l, View v, int position, long id) {
        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, new Intent().setData(uri));
        } else {
            // Launch activity to view/edit the currently selected item
            startActivity(new Intent(Intent.ACTION_EDIT, uri));
        }
    }

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

Intent深度剖析

那么,上面这句startActivity(new Intent(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函数中(见后续文章)。

转载于:https://blog.51cto.com/techgogogo/1608462

ContentProvider中gettype() 和MIME类型的理解相关推荐

  1. android 中MIME类型的理解

    初始MIME类型,是在学习ContentProvider的时候. 当在创建自己的ContentProvider的时,需要从抽象类ContentProvider中派生出自己的子类,并实现其中5个抽象方法 ...

  2. 对ContentProvider中getType方法的一点理解

    在上篇博客中我们介绍了自定义ContentProvider,但是遗漏掉了一个方法,那就是getType,自定义ContentProvider一般用不上getType方法,但我们还是一起来探究下这个方法 ...

  3. java中得到文件MIME类型的几种方法(转)

    本文转载自:http://hotsunshine.iteye.com/blog/857485 使用 javax.activation.MimetypesFileTypeMap 需要引入activati ...

  4. java web中文件类型,java web项目文件上传中常见的mime类型/文件类型校验、验证/只允许特定类型的文件(基于Apache的tika)...

    java代码 final Tika tika = new Tika(); Set allowMimeTypeAll = ImmutableSet.of("image/pjpeg", ...

  5. 在IIS中配置MIME类型组建Wap网站

    1.创建站点文件夹 首先你要在IIS上创建一个新的站点. 2.创建新的MIME类型 首先选择"WAP"站点的"属性",然后选择"HTTP 头" ...

  6. IE9 CSS 因 Mime 类型不匹配而被忽略“问题

    写页面的时候在chrome,fireforks等页面上显示正常,但是换成IE9之后就完全没有样式了.IE真是个奇葩的怪胎.它的报错信息是'CSS 因 Mime 类型不匹配而被忽略',也就是说所有的.c ...

  7. docx,pptx等正确的mime类型是什么?

    对于较早的* .doc文档,这已足够: header("Content-Type: application/msword"); 我应该为新的docx文档使用哪种mime类型? 还可 ...

  8. MIME类型,Content-Type

    //指定返回的是一个不能被客户端读取的流,必须被下载                Response.ContentType = "application/x-msdownload" ...

  9. MIME类型是什么意思

    MIME MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开.多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方 ...

最新文章

  1. 使用sourceInsight 提高代码编写效率
  2. 关于Android 8.0java.lang.SecurityException: Permission Denial错误的解决方法
  3. HTTP网页请求过程
  4. Java:多线程之线程池
  5. 配置ORACLE 客户端连接到数据库
  6. Python3 基础学习笔记 C09【文件和异常】
  7. 虚拟dom_从0到1实现一个虚拟DOM
  8. Android与iOS/WP8跨平台整合设计与开发_专栏
  9. ArcGIS For Flex学习之Mapping---Add LODs for extra zooming
  10. UbuntuHadoop集群搭建过程
  11. Dreamweaver CS6破解教程[序列号+破解补丁
  12. NPOI使用ShiftRows向excel插入行,并复制原有样式
  13. DM数据库中数据字典表分类及常用查询。
  14. 有趣的海盗分金币问题
  15. Alpha阶段敏捷冲刺②
  16. 课题三 数控机床的坐标系及编程规则
  17. LabVIEW调用第三方exe软件或操作操作控制第三方软件界面的控件,如操控烧录软件
  18. PMBOK第六版-目录
  19. 统计假设测验------(二)平均数的假设测验(t测验原理与公式)
  20. html5 底部导航栏,web前端html5手机端底部导航多种方法推荐

热门文章

  1. 在 ASP.NET Web 部件应用程序中使用服务器控件
  2. 基于Spring Security的认证方式_编程理解PasswordEncoder工作原理_Spring Security OAuth2.0认证授权---springcloud工作笔记125
  3. K8S_Google工作笔记0005---搭建k8s集群(kubeadm方式)
  4. java异常总结---1.java.lang.ClassNotFoundException: org.springframework.orm.hibernate4.support.OpenSessio
  5. html5学习笔记---01.HTML5介绍,02.HTML5的新特性
  6. test dword ptr [eax],eax ; probe page.
  7. 杭电2066一个人的旅行(spfa)
  8. 基于ext4j的带jar文件的java程序打包方法
  9. 随想录(矩阵计算的几种方法)
  10. mysql的时间用什么存储_MySQL存储时间类型选择的问题讲解