1 package com.hughes.android.dictionary;
4 import java.io.IOException;
5 import java.io.RandomAccessFile;
6 import java.util.ArrayList;
7 import java.util.Collections;
8 import java.util.LinkedHashSet;
11 import java.util.concurrent.Executor;
12 import java.util.concurrent.Executors;
13 import java.util.concurrent.atomic.AtomicBoolean;
15 import android.app.Activity;
16 import android.os.Bundle;
17 import android.os.Handler;
18 import android.text.Editable;
19 import android.text.TextWatcher;
20 import android.util.Log;
21 import android.view.View;
22 import android.view.ViewGroup;
23 import android.widget.BaseAdapter;
24 import android.widget.EditText;
25 import android.widget.ListView;
26 import android.widget.TextView;
28 import com.hughes.util.FileUtil;
30 public class Dictionary extends Activity {
32 public static final String INDEX_FORMAT = "%s_index_%d";
33 private File dictionaryFile = new File("/sdcard/dict-de-en.txt");
35 private RandomAccessFile dictionaryRaf;
36 private final Index[] indexes = new Index[2];
37 private final byte lang = Entry.LANG1;
39 final Handler uiHandler = new Handler();
41 private final Object mutex = new Object();
42 private Executor searchExecutor = Executors.newSingleThreadExecutor();
43 private SearchOperation searchOperation = null;
44 private List<Entry> entries = Collections.emptyList();
45 private DictionaryListAdapter dictionaryListAdapter = new DictionaryListAdapter();
47 /** Called when the activity is first created. */
49 public void onCreate(Bundle savedInstanceState) {
50 Log.d("THAD", "onCreate");
51 super.onCreate(savedInstanceState);
52 setContentView(R.layout.main);
54 EditText searchText = (EditText) findViewById(R.id.SearchText);
55 searchText.addTextChangedListener(new DictionaryTextWatcher());
57 ListView searchResults = (ListView) findViewById(R.id.SearchResults);
58 searchResults.setAdapter(dictionaryListAdapter);
61 } catch (Exception e) {
62 throw new RuntimeException(e);
64 onSearchTextChange("");
67 private void loadIndex() throws IOException, ClassNotFoundException {
68 Log.d("THAD", "enter loadIndex");
69 indexes[0] = new Index(String.format(INDEX_FORMAT, dictionaryFile
70 .getAbsolutePath(), Entry.LANG1));
71 dictionaryRaf = new RandomAccessFile(dictionaryFile, "r");
72 Log.d("THAD", "exit loadIndex");
75 void onSearchTextChange(final String searchText) {
76 Log.d("THAD", "onSearchTextChange: " + searchText);
77 synchronized (mutex) {
78 if (searchOperation != null) {
79 searchOperation.interrupted.set(true);
81 searchOperation = new SearchOperation(searchText);
83 searchExecutor.execute(searchOperation);
86 private final class SearchOperation implements Runnable {
87 final String searchText;
88 final int count = 100;
89 final AtomicBoolean interrupted = new AtomicBoolean(false);
91 public SearchOperation(final String searchText) {
92 this.searchText = searchText;
96 Log.d("THAD", "SearchOperation: " + searchText);
97 final List<Entry> newEntries = new ArrayList<Entry>(count);
99 final Index.Node node = indexes[lang].lookup(searchText);
100 final Set<Integer> entryOffsets = new LinkedHashSet<Integer>(count);
101 node.getDescendantEntryOffsets(entryOffsets, count);
102 for (final int entryOffset : entryOffsets) {
103 if (interrupted.get()) {
104 Log.d("THAD", "Interrupted while parsing entries.");
107 final String line = FileUtil.readLine(dictionaryRaf, entryOffset);
108 final Entry entry = new Entry(line);
109 newEntries.add(entry);
111 } catch (IOException e) {
112 Log.e("THAD", "Search failure.", e);
115 synchronized (mutex) {
116 if (interrupted.get()) {
119 entries = newEntries;
122 uiHandler.post(new Runnable() {
124 synchronized (mutex) {
125 dictionaryListAdapter.notifyDataSetChanged();
131 private class DictionaryListAdapter extends BaseAdapter {
133 public int getCount() {
134 synchronized (mutex) {
135 return entries.size();
139 public Object getItem(int position) {
140 synchronized (mutex) {
141 assert position < entries.size();
142 return entries.get(position).getFormattedEntry(lang);
146 public long getItemId(int position) {
150 public View getView(int position, View convertView, ViewGroup parent) {
151 TextView result = null;
152 if (convertView instanceof TextView) {
153 result = (TextView) convertView;
155 result = new TextView(parent.getContext());
157 result.setText((String) getItem(position));
163 private class DictionaryTextWatcher implements TextWatcher {
164 public void afterTextChanged(Editable searchText) {
165 onSearchTextChange(searchText.toString());
168 public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
172 public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
177 // TODO Auto-generated method stub