好想成为一个牛人,但是成为牛人太难了,需要一点一点的辛勤付出。最近在学习Android 应用程序编写,以前是搞C语言的,对JAVA这种面向对象的语言还是适应不过来,看了好多资料,下了好多例程,一边看一边学。感觉自己好笨,既然不知道下载官方SDK的时候,就自带了好多的例程(SDK文件夹内的sample文件夹),今天才知道,暗下决心,要把整个例程全部看懂。
第一个例程为ApiDemos,如果看过的人知道,我走上了一条不归路这个例程名字看似简单,其实非常复杂,它几乎把SDK常用的东西全部罗列出来,一个小部分自称一个体系,占用一个.java。总共200多个,哎,硬着头皮看吧。
首先找到mainfest.xml,找到avtivity的入口点,这是我第一次看到这么长的mainfest.xml(200多个Activity),里面好多的android.intent.action.MAIN标识,入门教程告诉我这是主Activity,从这里作为入口研究。为什么这么多标识主Activity的呢????不管了,先看代码。此时,找到了 ApiDemos.java 确定他就是主Activity。
如果从来没有看过这种方案的代码,肯定会看的稀里糊涂,经过我的几个钟头奋战,终于搞清楚了来龙去脉,原来好多的Activity公用一套代码实现这套代码就是ApiDemos.java 。它是怎么做到的呢???原来他们利用了mainfest.xml里面Activity的 label项,label项都被定义成了String 类型,而这些String类型 都被定义在了res/values/string.xml中,并且形式种类全是路径的形式,例如“ <string name="activity_dialog">App/Activity/Dialog</string>”所以说 ApiDemos.java 就通过解析所有的Activity的label,把Activity给归类了一下,然后再显示出来。举个例子就像ApiDemos.java 这些代码,给这个例程做了个目录,目录还分好几层,就跟书的章节一样,最后一层就是详细的内容(这里最后一层就是Activity实例)。
归纳一下上面说的,以前我们做个程序,如果这个程序有五个功能,我们一般会建立6个java文件,其中一个是个列表,用来指向5个功能。但是现在有200个功能,总不能第一个java文件依次列出200个选项,然后分别指向这200个功能吧。所以就在前面做了个目录,归类,最终导航到最终的Activity。
下面分析一下代码(请自行找代码)。
super.onCreate(savedInstanceState);
Intent intent = getIntent();
String path = intent.getStringExtra("com.example.android.apis.Path");
if (path == null) {
path = "";
}
android.R.layout.simple_list_item_1, new String[] { "title" },
new int[] { android.R.id.text1 }));
getListView().setTextFilterEnabled(true);
}
List<Map> myData = new ArrayList<Map>();
mainIntent.addCategory(Intent.CATEGORY_SAMPLE_CODE);
List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0);
return myData;
if (prefix.equals("")) {
prefixPath = null;
} else {
prefixPath = prefix.split("/");
}
int len = list.size();
Map<String, Boolean> entries = new HashMap<String, Boolean>();
ResolveInfo info = list.get(i);
CharSequence labelSeq = info.loadLabel(pm);
String label = labelSeq != null
? labelSeq.toString()
: info.activityInfo.name;
if (prefix.length() == 0 || label.startsWith(prefix)) {
String[] labelPath = label.split("/");
addItem(myData, nextLabel, activityIntent(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name));
} else {
if (entries.get(nextLabel) == null) {
addItem(myData, nextLabel, browseIntent(prefix.equals("") ? nextLabel : prefix + "/" + nextLabel));
entries.put(nextLabel, true);
}
}
}
}
return myData;
}
List<Map> myData = new ArrayList<Map>();
mainIntent.addCategory(Intent.CATEGORY_SAMPLE_CODE);
List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0);
return myData;
// prefixPath 从全文看,它的作用就是标注当前路径
if (prefix.equals("")) { //第一次调用确实为空 所以当前路径就是 null
prefixPath = null;
} else {
prefixPath = prefix.split("/"); //如果不为空,则把路径拆分,各个拆后的单词放在prefixPath中。
}
int len = list.size();
Map<String, Boolean> entries = new HashMap<String, Boolean>();
ResolveInfo info = list.get(i);
CharSequence labelSeq = info.loadLabel(pm);
String label = labelSeq != null
? labelSeq.toString()
: info.activityInfo.name; //label=当前Activity的lable标记,我们现在假设这个标记是“App/Activity/Dialog”
if (prefix.length() == 0 || label.startsWith(prefix)) { //函数传进来的参数如果为空,或者这个参数和label的前半截相匹配
String[] labelPath = label.split("/"); //把label分割,分割后就是labelPath={"App","Activity","Dialog"}
addItem(myData, nextLabel, activityIntent(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name));
} else { //如果当前路径还是 "App","Activity 不是 Dialog这种的,走else
addItem(myData, nextLabel, browseIntent(prefix.equals("") ? nextLabel : prefix + "/" + nextLabel));
entries.put(nextLabel, true);
}
}
}
}
return myData;
}