字典Directory类的分析,在这个程序中这个Directory相当于是数据源,也就是相当于数据库,而DictionaryProvider相当于操作这个数据库的类
public class Dictionary {
public static class Word {
public final String word;
public final String definition;
public Word(String word, String definition) {
this.word = word;
this.definition = definition;
}
}
private static final Dictionary sInstance = new Dictionary();
public static Dictionary getInstance() {
return sInstance;
}
private final Map<String, List<Word>> mDict = new ConcurrentHashMap<String, List<Word>>();
private Dictionary() {
}
private boolean mLoaded = false;
/**
* Loads the words and definitions if they haven't been loaded already.
*
* @param resources Used to load the file containing the words and definitions.
*/
public synchronized void ensureLoaded(final Resources resources) {
if (mLoaded) return;
new Thread(new Runnable() {
public void run() {
try {
loadWords(resources);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}).start();
}
private synchronized void loadWords(Resources resources) throws IOException {
if (mLoaded) return;
Log.d("dict", "loading words");
InputStream inputStream = resources.openRawResource(R.raw.definitions);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
try {
String line;
while((line = reader.readLine()) != null) {
String[] strings = TextUtils.split(line, "-");
if (strings.length < 2) continue;
addWord(strings[0].trim(), strings[1].trim());
}
} finally {
reader.close();
}
mLoaded = true;
}
public List<Word> getMatches(String query) {
List<Word> list = mDict.get(query);
return list == null ? Collections.EMPTY_LIST : list;
}
private void addWord(String word, String definition) {
final Word theWord = new Word(word, definition);
final int len = word.length();
for (int i = 0; i < len; i++) {
final String prefix = word.substring(0, len - i);
addMatch(prefix, theWord);
}
}
private void addMatch(String query, Word word) {
List<Word> matches = mDict.get(query);
if (matches == null) {
matches = new ArrayList<Word>();
mDict.put(query, matches);
}
matches.add(word);
}
}
当我们查询以字母g开头的单词时会将所有以g开头的单词显示出来:
这里是启动一个线程来记载这些单词的:
public synchronized void ensureLoaded(final Resources resources) {
if (mLoaded) return;
new Thread(new Runnable() {
public void run() {
try {
loadWords(resources);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}).start();
}
private synchronized void loadWords(Resources resources) throws IOException {
if (mLoaded) return;
Log.d("dict", "loading words");
InputStream inputStream = resources.openRawResource(R.raw.definitions);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
try {
String line;
while((line = reader.readLine()) != null) {
String[] strings = TextUtils.split(line, "-");
if (strings.length < 2) continue;
addWord(strings[0].trim(), strings[1].trim());
}
} finally {
reader.close();
}
mLoaded = true;
}
这里用一个变量mLoad来控制是否加载单词,如果加载了即使下次调用了这个线程也会推出这个线程。这里按照<Java多线程设计模式>上应该是属于Balking(不需要的话,就算了吧),在警戒条件不成立时,线程会直接退出。
private void addWord(String word, String definition) {
final Word theWord = new Word(word, definition);
final int len = word.length();
for (int i = 0; i < len; i++) {
final String prefix = word.substring(0, len - i);
addMatch(prefix, theWord);
}
}
将这个单词的每个字母加到列表里面
private void addMatch(String query, Word word) {
List<Word> matches = mDict.get(query);
if (matches == null) {
matches = new ArrayList<Word>();
mDict.put(query, matches);
}
matches.add(word);
}
如果某个单词的某个字母作为键在这个private final Map<String, List<Word>> mDict = new ConcurrentHashMap<String, List<Word>>();里面是否有值,如果有就在这个键对应的值里面加上,如果没有就创建一个然后加上。
这里需要注意一点:
List<Word> matches = mDict.get(query);
matches.add(word);
也就是说返回的是List的地址,我在这上面添加数据,在mDict里面也相应的改变了
这样的话当要搜索某个字母开头的单词的话:
public List<Word> getMatches(String query) {
List<Word> list = mDict.get(query);
return list == null ? Collections.EMPTY_LIST : list;
}
只要从mDict里面返回这个键对应的所有值就可以了。