当前位置:  编程技术>移动开发
本页文章导读:
    ▪Intent 跟 Intent Filter        Intent 和 Intent Filter 转自:http://www.cnblogs.com/Android_2011/archive/2011/06/12/2078643.html   Intent 和 Intent Filter   Android 应用程序中有三大核心组件: Activity, Service, Broadcast Receiver 都是通过被称之为意.........
    ▪ NSNull功用        NSNull作用 Directly from Apple: "The NSNull class defines a singleton object you use to represent null values in situations where nil is prohibited as a value (typically in a collection object such as an array or a dictionary)."   NSNull表示一.........
    ▪ DEFAULT_KEYS_SHORTCUT 效能的验证 及其 源码实现分析       DEFAULT_KEYS_SHORTCUT 功能的验证 及其 源码实现分析 转自:http://blog.csdn.net/silenceburn/article/details/6069988 作者:silenceburn Activity的setDefaultKeyMode (int mode) 方法用来设置一个Activity的默认的按键模式.........

[1]Intent 跟 Intent Filter
    来源: 互联网  发布时间: 2014-02-18
Intent 和 Intent Filter

转自:http://www.cnblogs.com/Android_2011/archive/2011/06/12/2078643.html

 

Intent 和 Intent Filter

 

Android 应用程序中有三大核心组件: Activity, Service, Broadcast Receiver 都是通过被称之为意图的消息运行。Intent messaging is a facility for late run-time binding between components in the same or different applications. 意图本身一个 Intent 对象,它保存了对要执行操作的抽象描述—对于broadcasts来说,则表示对已经发生并且正要报告的操作。对这下三种组件,发送intents分别有不同的机制。

  • 传递一个Intent对象到 Context.startActivity(intent) 或者 Activity.startActivity ForResult(int) 去运行一个Activity(可以在通过此方式启动后的Activity中调用 Activity.setResult() 设置结果参数,该参数将会在启动当前activity的activity中被接收---可以通过onActivityResult(int requestCode, int resultCode, Intent data) 接收)
  • 传递一个Intent对象到 Context.startService(intent) 去启动一个service 或者 传递一个新的指令到正在运行的service中。另外,还可以通过 Context.bindService(intent) 去绑定一个Service。(在调用组件和目标Service 建立一个连接)
  • 传递一个Intent对象到 任何一个broadcast methods (如: Context.sendBroadcast() , Context.sendOrderedBroadcast(), Context.sendStickyBroadcast() ) 该intent将被传递给所有已经被注册的broadcast receiver中。

在以上的三种情况下,当Intent被传递出后,Android系统会找到适合的activity,service,或者是多个broadcast receiver去响应这个intent。,这三种情况不会存在重叠的部分,它们相互独立,互不干扰。(调用Context.startActivity()后 intent只会被相应的activity接收到)

 

Intent Object

一个Intent对象是一个信息包。它包含了要接收此Intent的组件需要的信息(例如需要的动作和动作需要的信息)和 android 系统需要的信息(要处理此Intent的组件的类别和怎样启动它)

总的来说,Intent Object 主要包括以下信息:

Component name 

处理Intent 的组件名称。此字段是一个 ComponentName object---它是目标的组件的完整限定名(包名+类名) 例如: “com.android,.test.TestActivity” .

该字段是可选的。如果设置了此字段,那么 Intent Object 将会被传递到这个组件名所对应的类的实例中。 如果没有设置,Android 会用 Intent object 中的其它信息去定位到一个合适的目标组件中。 (称之为 : Intent 解析。。。这个稍后会讲到)

设置Component name 可以通过 setComponent() , setClass() 或者 setClassName()进行设置。 可以通过 getComponent() 进行读取

动作(Action)

一个字符串,代表要执行的动作。 -- 或者,对于 broadcase intents 来说,表示正在发生,并且被报告的动作。Intent 类中 定义了许多动作常量。 如下:

 

Constent( 常量)

Target Component (目标组件)

Action (动作 )

ACTION_CALL

activity

初始化一个电话呼叫

ACTION_EDIT

activity

显示用户要编辑的数据

ACTION_MAIN

activity

将该Activity作为task的第一个Activity ,没有数据输入,也没有数据返回

ACTION_SYNC

activity

在设备上同步服务器上的数据

ACTION_BATTERY_LOW

broadcast receiver

电量不足的警告

ACTION_HEADSET_PLUG

broadcast receiver

耳机插入设备,或者从设备中拔出

ACTION_SCREEN_ON

Broadcast receiver

屏幕已经点亮

ACTION_TIMEZONE_CHANGED

Broadcast receiver

时区设置改变

 

你也可以定义自己的 action strings 来激活组件。自定义的action 应该包含包名作为前缀: 例如"com.example.project.SHOW_COLOR".

Action 很大程度上决定 Intent余下部分的结构。 ---- 特别是:data 和 extras 两个字段。就像一个方法的方法名通常决定了方法的参数和返回值。 基于这个原因,应该给action 命名一个尽可能明确的名字。 可以通过 setAction() 设置action,通过 getAction() 进行获取.

Data

Data属性有两部分构成: 数据URI 和 数据MIME type 。 action的定义往往决定了data该如何定义。 例如: 如果 一个Intent的 action 为 ACTION_EDIT 那么它对应的data 应该包含待编辑的数据的URI . 如果一个action 为:ACTION_CALL ,那么data 应该为 tel: 电话号码的URI . 类似的, 如果action 为ACTION_VIEW 那么data 应该为: http: URI , 接收到的activity 将会下载并显示相应的数据。

当一个Intent 和 有能力处理此Intent的组件进行匹配时, 除了 data的URI以外,了解data的类型(MIME Type)也很重要。 例如: 一个显示图片的组件 不应该去播放声音文件。

许多情况下,data type 可以从URI中推测出。 尤其是: URI = content: URIs这时候数据通常是位于本设备上而且是由某个content provider来控制的。即便如此,我们仍然可以明确的在 Intent object上设置一个 data type. setData() 方法只能设置URI, setType() 设置MIME type, setDataAndType() 可以对二者都进行设置, 获取URI 和 data type 可分别调用 getData() 和 getType() 方法。

Category

一个字符串, 包含了处理该Intent的组件的种类信息, 起着对action的补充说明作用.

一个Intent对象可以有任意多个 category。和action 一样, 在Intent class 中也定义了几个 category 常量。。 如下:

Constant

Meaning

CATEGORY_BROWSABLE

目标Activity可以使用浏览器显示数据

CATEGORY_GADGET

The activity can be embedded inside of another activity that hosts gadgets.

该activity可以被包含在另外一个装载小工具的activity中.

CATEGORY_HOME

The activity displays the home screen, the first screen the user sees when the device is turned on or when the HOME key is pressed.

CATEGORY_LAUNCHER

The activity can be the initial activity of a task and is listed in the top-level application launcher.

可以让一个activity出现在launcher

CATEGORY_PREFERENCE

The target activity is a preference panel.

该activity是一个选项面板

 

addCategory() 添加一个 category

removeCategory() 删除一个 category()

getCategorys() 获取所有的category()

Extras

为键-值对形式的附加信息. 例如ACTION_TIMEZONE_CHANGED的intent有一个"time-zone"附加信息来指明新的时区, 而ACTION_HEADSET_PLUG有一个"state"附加信息来指示耳机是被插入还是被拔出.

intent对象有一系列put...()和set...()方法来设定和获取附加信息. 这些方法和Bundle对象很像. 事实上附加信息可以使用putExtras()和getExtras()作为Bundle来读和写.

Flags

有各种各样的标志,许多指示Android系统如何去启动一个活动(例如,活动应该属于那个任务)和启动之后如何对待它(例如,它是否属于最近的活动列表)。所有这些标志都定义在Intent类中。

 

 

Intent Resolution

Intent 有两种形式:

l 显示意图指定一个目标组件通过其name( Component name field), 由于组件名称通常不会被其它应用程序的开发者知道。所以,显示意图通常用在应用程序内部消息。----如:一个Activity 启动一个从属的service或者启动另一个activity

l 隐式意图不指定目标组件名称(component name 是空的)隐式意图通常用于去激活其它应用程序的组件

Android 传递了一个显示意图给一个被指定的目标类的实例 。被传递的 intent object 只是定义了component name -- 它决定了将会有那个组件去处理这个intent。

针对隐式意图需要不同的策略。在缺乏一个被指定的target的情况下,android系统必须找到最适合的组件去处理这个intent ---- 一个单一的activity 或者 service 去执行一个请求动作或者一组broadcase receiver 去响应广播通知.

它通过将intent 对象中的内容 和 意图过滤器(intent filters)进行比较。android系统根据intent filter打开可以接收intent的组件. 如果一个组件没有intent filter, 那么它只能接受显式intent. 如果有, 则能同时接受二者.。

Only three aspects of an Intent object are consulted when the object is tested against an intent filter:

当一个intent和intent过滤器进行比较时只会考虑以下三方面:

action  
data (both URI and data type)  
category

Intent filters

要告诉android系统哪个intent它们可以处理,activities,services,和 broadcast receivers 必须设置一个或者多个intent过滤器。每个过滤器描述了组件的一种能力,它过滤掉不想要的intent,留下想要的。显示意图则不用考虑这些。

一个过滤器中包含 一个Intent object 中的三个属性 action,data,catrgory 。一个隐式意图必须要通过这三项测试才能传递到 包含该过滤器的组件中。

测试1:Action test

<intent-filter . . . >
    <action android:name="com.example.project.SHOW_CURRENT" />
    <action android:name="com.example.project.SHOW_RECENT" />
    <action android:name="com.example.project.SHOW_PENDING" />
    . . .
</intent-filter>

如实例所示,当一个intent对象只能命名一个单一的action,一个过滤器则可以列出多个action。这个列表也可以是空的, 一个过滤器必须包含一个 <action> element ,否则它将阻止所有的intents要通过这个测试,在intent被指定的action必须匹配在过滤器中所列的action的其中之一。如果一个intent对象或者过滤器没有指定action。 结果如下 :

l 如果一个filter 没有指定任何action ,那么则没有任何intent会被匹配。所以,所有的intent将不会通过此测试。

l 另一方面,如果一个intent对象没有指定任何action,那么将自动通过此测试—只要这个过滤器中有至少一个action

测试2:Category test

<intent-filter . . . > 
<category android:name="android.intent.category.DEFAULT" /> 
<category android:name="android.intent.category.BROWSABLE" /> 
    . . . 
</intent-filter>

要通过category测试, Intent对象中包含的每个category必须匹配filter中的一个。Filter可以列出额外的category,但是不能漏掉 intent 对象包含的任意一个category。

原则上,一个没有任何categorys的 Intent object 将总是通过此测试。大多数情况下是正确的。然而,也有例外,android对待所有传入 startActivity() 中的隐式视图,都认为它们至少包含了一个 category --- "android.intent.category.DEFAULT". . 因此,希望接收这些隐式意图的activities必须在在它们的 intent filters 中包含”android.intent.category.DEFAULT” ..有(对于包含"android.intent.action.MAIN" and "android.intent.category.LAUNCHER"的filter 则是例外。因为它们标记了此activity开启了一个新的task 和 将出现在 auncher screen。它们也可以包含“com.intent.category.DEFAULT”,但没必要)

测试3:Data test

类似于action, categories, data也是 intent filter 中的一个子节点, 可以设置多个 data节点,也可以一个不设置。

如下图:

<intent-filter . . . > 
<data android:mimeType="video/mpeg" android:scheme="http" . . . /> 
<data android:mimeType="audio/mpeg" android:scheme="http" . . . /> 
    . . . 
</intent-filter>

每个< data > 元素可以指定一个 URI 和 一个 data type (MIME media type) . URI 有以下几个属性组成 : schema, host,port,path

Schema://host:port/path

例如:

content://com.example.project:200/folder/subfolder/etc

在上例中 schema 是 content: host: com.example.project

Port: 200 Path: folder/subfolder/etc

主机 host 和 port 一起组成了URI authority,如果没有指定 host,那么port将被忽略。

<data>节点中的属性都是可选的,但它们并非相互独立。要使一个authority 有意义,必须要指定 scheme 。 要是 path 有意义, scheme 和 authority(host:port) 必须指定。

当Intent对象中的URI 和 intent filter 进行比较时,它只会进行部门比较。 例如: 如果一个 filter 只指定了一个scheme , 那么所有包含该scheme的URI都会匹配。 如果一个filter只指定了 scheme 和 authority ,没有path, 那么所有包含此scheme 和 authority 将会匹配。如果一个filter指定了一个scheme,authority, 和一个path, 那么只有包含同样的 scheme,authoritym,path会匹配。 但是,对于path,我们可以使用通配符进行部门匹配。

<data>节点的 type 属性指定了 data的MIME type。 它比在filter中的URI 更常见 intent对象和filter都可以使用 “*” 通配符作为子类型 – 例如: "text/*" or "audio/*"--- 表示所有子类型都匹配。

data test 会将 intent对象中的URI 和 data type 与filter指定的都进行比较。 规则如下:

a) 如果一个intent 没有指定URI 和 data type , 那么如果filter中也是同样,则通过测试。

b) 如果一个iintent 有URI 但是没有 data type(或者是data type不能从uri中推断出来 ) 只能通过这样的filter: uri匹配, 并且不指定类型. 这种情况限于类似mailto:和tel:这样的不指定实际数据的uri.

c) 如果一个intent 包含 data type 但是没有 uri ,那么 filter中列出相同的data type 并且没有指定URI 则通过测试。

d) 如果一个intent包含一个URI 和data type (或者data type 可以从URI中推断出来),那么filter列出的有相同data type ,intent对象的uri要么和filter中的uri匹配,要么intent的uri为 content: or file: 并且filter不指定uri

如果一个Intent 可以通过多个activity或者filter的filter,那么用户将会被询问需要激活哪个组件。 如果一个都没有的话,将会抛出异常。

 

Common cases

这个规则是针对 data test 中的规则d) ,它反映出组件可以从一个file或者content provider 获取本地数据。因此,filters 可以是设置data type并且没有必要明确的将 scheme 命名为 content: 和 file: 。

下面的 <data>元素,告诉android该组件可以从content provider中获取image data 并显示她。

<data android:mimeType="image/*" />

由于大部分可用的数据都是由content provider提供, 指定数据类型但不指定uri的filter是最常见的情况.

Another common configuration is filters with a scheme and a data type. For example, a <data> element like the following tells Android that the component can get video data from the network and display it:

设置了 scheme 和 data type是 另一个比较常见的配置是 。下面的 <data>元素,告诉android该组件可以从网上获取video并显示

<data android:scheme="http" android:type="video/*" />

考虑当用户在一个web page上点了一个链接后,浏览器应用程序做了什么。 它首先会试图去显示该数据(当做一个html页来处理)。如果它不能显示此数据,它会使用一个设置 scheme 和 data type 的隐式意图 去启动一个能显示此数据的activity。如果没有找到接受者,它会调用下载管理器去下载该数据,然后将其放在content provider的控制之下,这样很多activitys (那些之命名了datatype)可以处理该数据

大部分应用程序还有一种方式可以单独启动,不用去引用特别的数据。那些要启动应用程序的activity 必须 设置 "android.intent.action.MAIN" 作为action。

如果还要显示在程序启动器上则必须设置 "android.intent.category.LAUNCHER" 为 category.

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

 

 

 

 

 

 

 

 

 

 


    
[2] NSNull功用
    来源: 互联网  发布时间: 2014-02-18
NSNull作用

Directly from Apple: "The NSNull class defines a singleton object you use to represent null values in situations where nil is prohibited as a value (typically in a collection object such as an array or a dictionary)."

 

NSNull表示一个为空值的一个对象,使用的一个例子:

NSMutableArray *controllers = [[NSMutableArray alloc] init];
for (unsigned i = 0; i < kNumberOfPages; i++) {
    [controllers addObject:[NSNull null]];
 在Objective-c中,对于像NSArray这样的类型,nil或NULL不能做为加到其中的Object,如果定义了一个NSArray,为其分配了内存,又想设置其中的内容为空,则可以用[NSNULL null返回的对对象来初始化NSArray中的内容

    
[3] DEFAULT_KEYS_SHORTCUT 效能的验证 及其 源码实现分析
    来源: 互联网  发布时间: 2014-02-18
DEFAULT_KEYS_SHORTCUT 功能的验证 及其 源码实现分析

转自:http://blog.csdn.net/silenceburn/article/details/6069988

作者:silenceburn

Activity的setDefaultKeyMode (int mode) 方法用来设置一个Activity的默认的按键模式。

具体介绍可以参见我写的 setDefaultKeyMode 用法介绍   一文。

地址是:   http://blog.csdn.net/silenceburn/archive/2010/12/11/6069645.aspx

 

其中有一种模式是 DEFAULT_KEYS_SHORTCUT ,本文从API文档对此模式的介绍出发,

首先通过编写示例代码,介绍其功能用法,然后通过追踪源码,简单介绍此模式在android源码中是如何实现的。

 

1.  关于 DEFAULT_KEYS_SHORTCUT  的 API文档介绍

Use with setDefaultKeyMode(int) to execute a menu shortcut in default key handling.

That is, the user does not need to hold down the menu key to execute menu shortcuts.

 

从字面上看,其含义是指,将默认的按键输入作为菜单快捷键进行处理。

也就是说,用户不需要按下menu按键,就可以处理菜单快捷键,听起来非常神奇,究竟是不是这样呢?

 

 

2.编写示例程序

我们编写一个程序验证一下其功能,首先新建一个工程,并设置默认按键模式为 DEFAULT_KEYS_SHORTCUT

 

[java] view plaincopy
  • package com.silenceburn;  
  •   
  • import android.app.Activity;  
  • import android.os.Bundle;  
  •   
  • public class MenuShortCutTester extends Activity {  
  •     /** Called when the activity is first created. */  
  •     @Override  
  •     public void onCreate(Bundle savedInstanceState) {  
  •         super.onCreate(savedInstanceState);  
  •         setContentView(R.layout.main);  
  •           
  •         setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);  
  •     }  
  • }  
  •  

     

     

    为默认的main.xml中的TextView增加一个id属性,之后我们会用菜单选项控制这行字的颜色

     

    [xhtml] view plaincopy
  • <?xml version="1.0" encoding="utf-8"?>  
  • <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  •     android:orientation="vertical"  
  •     android:layout_width="fill_parent"  
  •     android:layout_height="fill_parent"  
  •     >  
  • <TextView   
  •     android:id="@+id/myText"   
  •     android:layout_width="fill_parent"   
  •     android:layout_height="wrap_content"   
  •     android:text="@string/hello"  
  •     />  
  • </LinearLayout>  
  •  

     

     

    使用findViewById获取上一步中定义了id的文本对象,将其引用保存在成员变量b中。

    重写onPrepareOptionsMenu方法,增加我们自己的菜单项,并注册快捷键,同时增加菜单点击的响应事件。

     

    [java] view plaincopy
  • package com.silenceburn;  
  •   
  • import android.app.Activity;  
  • import android.os.Bundle;  
  • import android.view.Menu;  
  • import android.view.MenuItem;  
  • import android.view.MenuItem.OnMenuItemClickListener;  
  • import android.widget.TextView;  
  •   
  • public class MenuShortCutTester extends Activity {  
  •     /** Called when the activity is first created. */  
  •     TextView b;  
  •       
  •     @Override  
  •     public void onCreate(Bundle savedInstanceState) {  
  •         super.onCreate(savedInstanceState);  
  •         setContentView(R.layout.main);  
  •           
  •         b = (TextView) this.findViewById(R.id.myText);  
  •           
  •         setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);  
  •     }  
  •       
  •     @Override  
  •     public boolean onPrepareOptionsMenu(Menu menu) {  
  •         // TODO Auto-generated method stub  
  •         super.onPrepareOptionsMenu(menu);  
  •           
  •         menu.removeItem(0);  
  •         menu.removeItem(1);  
  •         menu.add( 0, 0, 0, "One").setShortcut('0', '0').setOnMenuItemClickListener(new OnMenuItemClickListener(){  
  •   
  •             @Override  
  •             public boolean onMenuItemClick(MenuItem item) {  
  •                 // TODO Auto-generated method stub  
  •                 b.setBackgroundColor(android.graphics.Color.RED);  
  •                 return true;  
  •             }});  
  •         menu.add( 0, 1, 0, "Two").setShortcut('1', '1').setOnMenuItemClickListener(new OnMenuItemClickListener(){  
  •   
  •             @Override  
  •             public boolean onMenuItemClick(MenuItem item) {  
  •                 // TODO Auto-generated method stub  
  •                 b.setBackgroundColor(android.graphics.Color.GREEN);  
  •                 return true;  
  •             }});   
  •           
  •         return true;  
  •     }  
  • }  
  •  

     

     

    注意我们一共注册了两个菜单项,

    一个叫“One”,点击时将文本对象 b 的背景颜色改为红色,同时定义其快捷键为0

    一个叫“Two”,点击时将文本对象 b 的背景颜色改为绿色,同时定义其快捷键为1

     

    至此示例程序完成。

     

    3.验证使用示例程序

    启动AVD,运行上述程序,程序启动后,我们应当看到是黑底灰字,点击menu按钮,可以看到One和Two两个菜单选项。

    如下图所示:

     

    目前Menu是打开状态,

    点击One ,将把“helloworld...”字样的背景色变为红色,

    点击Two ,将把“helloworld...”字样的背景色变为红绿色。

    或者我们点设置好的快捷键 0 和 1,发现可以直接调用菜单选项控制颜色变化。 

     

    到目前为止一切都很正常,不过,神奇的现在来了! 

     

    我们首先关闭菜单,

    然后直接点键盘键"0“,看看会发生什么。再直接点键盘键"1" ,看看会发生什么。

    哈哈,在没有激活菜单的情况下,菜单项快捷键被直接调用了!根本不需要打开菜单,就可以用激活菜单快捷键!

     

    什么?有位同学说快捷键就应该是这样子把,那好,请你把 onCreate 里面的

    setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT); 改为 setDefaultKeyMode(DEFAULT_KEYS_DISABLE);

    然后再运行试试,在不打开菜单的情况下,你就是把 0 和 1 按坏,系统也不会理你的呵呵

     

    4.浅析实现原理

    那么这神奇的功能是如何实现的呢?我们试着通过分析android源码找到答案。

     

    首先顺藤摸瓜,我们找一找系统是如何处理 DEFAULT_KEYS_SHORTCUT 关键字的,

    在Activity.java中可以找到如下代码片段:

     

     

    [java] view plaincopy
  • if (mDefaultKeyMode == DEFAULT_KEYS_DISABLE) {  
  •     return false;  
  • } else if (mDefaultKeyMode == DEFAULT_KEYS_SHORTCUT) {  
  •     if (getWindow().performPanelShortcut(Window.FEATURE_OPTIONS_PANEL,   
  •             keyCode, event, Menu.FLAG_ALWAYS_PERFORM_CLOSE)) {  
  •         return true;  
  •     }  
  •     return false;  
  • }  
  •  

     

    由此可知,当系统检测到 DEFAULT_KEYS_SHORTCUT 关键字时,实际调用了

    getWindow().performPanelShortcut(Window.FEATURE_OPTIONS_PANEL,

    keyCode, event,Menu.FLAG_ALWAYS_PERFORM_CLOSE)

     

    我们继续追寻,但是这里会遇到一个困难,就是查阅API文档你会发现,performPanelShortcut函数是个纯虚函数!

    接下来该怎么办呢?既然功能顺利执行了,那么这个纯虚函数一定会有一个实现的。这个实现类必然是window类的子类。

    所以我们在OnCreate里面加上一行代码 Window w =  this.getWindow();

    然后通过Eclipse的调试器,利用RTTI查看其实现类,结果如下图:

     

     

    可以看的很清楚,实现类是 PhoneWindow ,

    这样我们就可以到 PhoneWindow 的源码中去查找performPanelShortcut的实现了。

     

    在PhoneWindow.java中我们可以看到如下代码片段:

     

    [java] view plaincopy
  • // Only try to perform menu shortcuts if preparePanel returned true (possible false  
  • // return value from application not wanting to show the menu).  
  • if ((st.isPrepared || preparePanel(st, event)) && st.menu != null) {  
  •     // The menu is prepared now, perform the shortcut on it  
  •     handled = st.menu.performShortcut(keyCode, event, flags);  
  • }  
  •  

     

    终于看到menu字样了,这里我们可以看到 if 里面描述的调用条件,

    首先当前panel必须已经准备好了(你可以用 onPreparePanel 截获到准备请求),

    其次,当前panel必须是有Menu的!(st.menu != null),

    从这里我们可以明白DEFAULT_KEYS_SHORTCUT对于没有menu的应用是没有任何效果的。

    而且在另一处代码我们会看到还要进行 isShortCut 的判断,所以对于没有快捷键的菜单也是没有任何效果的。

     

    那么我们再看看 preparePanel 里面是如何实现的,在其实现中可以找到如下代码片段:

     

    [java] view plaincopy
  • // Callback and return if the callback does not want to show the menu  
  • if (!cb.onPreparePanel(st.featureId, st.createdPanelView, st.menu)) {  
  •     return false;  
  • }  
  •  

     

    至此,就完全明白了!代码在这里回调了 onPreparePanel ,而 onPreparePanel  中会回调  onPrepareOptionsMenu ,

    而onPrepareOptionsMenu ,就是我们自己写实现自定义菜单的地方了。

     

    为了验证上述推导,我们在onPrepareOptionsMenu 中放入断点,然后在菜单关闭的情况下,输入快捷键,

    运行到断点后查看调用堆栈,入下图所示:

     

     

     

    堆栈调用顺序可以很清楚的看出我们的推导过程是正确的。至此 DEFAULT_KEYS_SHORTCUT 的实现分析完毕。

     

     

    总结:

     

    我之所以非常喜爱和看好android平台,就是因为她是开源的,

    当我们对任何一个问题有疑问时,都可以把她扒光了细看,呵呵。

    而apple的IOS,尽管你很美,但是你的内心实在太难捉摸了。

     

    从本文的分析过程可以看出,平台任何一个看似神奇的功能的实现,

    背后都有安卓源码开发者们大巧不工重剑无锋的的实现。

     

    本文对DEFAULT_KEYS_SHORTCUT的分析实际上是很浅显的,

    如果细看源码,会发现更多的有意思的地方的。

     

    学习安卓,

    也许源码就是最好的老师。^_^


        
    最新技术文章:
    ▪Android开发之登录验证实例教程
    ▪Android开发之注册登录方法示例
    ▪Android获取手机SIM卡运营商信息的方法
    ▪Android实现将已发送的短信写入短信数据库的...
    ▪Android发送短信功能代码
    ▪Android根据电话号码获得联系人头像实例代码
    ▪Android中GPS定位的用法实例
    ▪Android实现退出时关闭所有Activity的方法
    ▪Android实现文件的分割和组装
    ▪Android录音应用实例教程
    ▪Android双击返回键退出程序的实现方法
    ▪Android实现侦听电池状态显示、电量及充电动...
    ▪Android获取当前已连接的wifi信号强度的方法
    ▪Android实现动态显示或隐藏密码输入框的内容
    ▪根据USER-AGENT判断手机类型并跳转到相应的app...
    ▪Android Touch事件分发过程详解
    ▪Android中实现为TextView添加多个可点击的文本
    ▪Android程序设计之AIDL实例详解
    ▪Android显式启动与隐式启动Activity的区别介绍
    ▪Android按钮单击事件的四种常用写法总结
    ▪Android消息处理机制Looper和Handler详解
    ▪Android实现Back功能代码片段总结
    ▪Android实用的代码片段 常用代码总结
    ▪Android实现弹出键盘的方法
    ▪Android中通过view方式获取当前Activity的屏幕截...
    ▪Android提高之自定义Menu(TabMenu)实现方法
    ▪Android提高之多方向抽屉实现方法
    ▪Android提高之MediaPlayer播放网络音频的实现方法...
    ▪Android提高之MediaPlayer播放网络视频的实现方法...
    ▪Android提高之手游转电视游戏的模拟操控
     


    站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3