分析代码,首先查看Androidmanifest.xml文件中的启动activity,如下所示:
<activity android:name="ApiDemos">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
通过名为"LAUNCHER"的category,可以知道Apidemo首先启动的activity是ApiDemos,我们就从ApiDemos.java开始分析。通过在模拟器中运行ApiDemos,可以看到ApiDemos包含了许多单独的实例,那么程序是如何组织起这些实例的呢?通过下面对具体代码的分析,我们可以发现实际上ApiDemos.java中提供了一个统一的管理界面,这个管理界面包含了一个树形结构的目录,这个树形结构的目录就是通过ListActivity实现的。
此处结合着网上一些人对ApiDemos.java文件的解析,为代码添加进去了自己的注释。如下所示:
package com.example.android.apis;
import android.app.ListActivity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.view.View;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/*
* ApiDemos类通过解析AnadroidManifest.xml文件中注册的各个Activity的label信息,生成应用程序的各级显示目录。
* label信息约定为此Activity的目录信息,例如DialogActivity的label的信息为“@string/activity_dialog”,
* 即为“App/Activity/Dialog”。也就是想要运行DialogActivity,需要先进入第一级目录的App,然后第二级目录的
* Activity,最后点击第三级目录的Dialog,就会出现DialogActivity的运行效果。
*/
public class ApiDemos extends ListActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//获取启动此Activity的Intent
Intent intent = getIntent();
//获取到Intent中附带的path信息,在第一级目录中此path信息为空
String path = intent.getStringExtra("com.example.android.apis.Path");
if (path == null) {
path = "";
}
/*
* 此处并没有使用setContentView()函数来加载一个layout文件,而是使用setListAdapter(ListAdapter)
* 函数自动的加载一个ListView的显示。ListAdapter可以使用的子类包括:arrayAdapter, SimpleAdapter,
* CursorAdapter。此处新建了一个SimpleAdapter,其list数据源data通过getData()函数获得。
*/
setListAdapter(new SimpleAdapter(this, getData(path),
android.R.layout.simple_list_item_1, new String[] { "title" },
new int[] { android.R.id.text1 }));
/*
* 相当于“ListView lv = getListView(); lv.setTextFilterEnabled(true);”。
* 为ListView添加过滤功能,这一在某一级目录下根据用户输入的前几个字母,只显示过滤后相匹配的列表项。
*/
getListView().setTextFilterEnabled(true);
}
// 该方法用于获取当前所在的目录信息,并生成SimpleAdapter中list项。
protected List<Map<String, Object>> getData(String prefix) {
//新建一个名为myData的List,用于返回。
List<Map<String, Object>> myData = new ArrayList<Map<String, Object>>();
//新建一个action为MAIN的Intent
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
//限定Intent的category为SAMPLE_CODE。这就限定了该Intent只能跳向符合这两项的Activity。
mainIntent.addCategory(Intent.CATEGORY_SAMPLE_CODE);
//建立一个包含全局包信息的PackageManager实例pm
PackageManager pm = getPackageManager();
//获取到所有可以由mainIntent跳转的Activity信息,返回值为List<ResolveInfo>
List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0);
if (null == list){
return myData;
}
// 字符串数组prefixPath用于存放目录中去除“/”后的各个目录名字,
String[] prefixPath;
//字符串prefixWithSlash用于存放目录名
String prefixWithSlash = prefix;
if (prefix.equals(""))