英文词典是手机中经常使用的应用。因此,在本文将结合Android 来讨论如何实现一个Android版的英文词典。实现英文词典的方法很多。在本文使用了SQLite数据库来保存英文单词信息。系统通过SQLite数据库中保存的单词信息来查找到与指定英文对应的中文信息。
实现电子词典要解决的技术问题及初步的解答。
在本节将给出实现电子词典需要解决的主要技术问题,并给出这些技术问题的初步答案或提示。关于详细的答案和代码请读者参阅本文后面的内容。
主要技术问题及解答如下:
1. 如何将SQLite数据库(dictionary.db文件)与apk文件一起发布?
解答:可以将dictionary.db文件复制到Eclipse Android工程中的res\raw目录中,
2. 如何将打开res\raw目录中的数据库文件?
解答:在Android中不能直接打开res\raw目录中的数据库文件,而需要在程序第一次启动时将该文件复制到手机内存或SD卡的某个目录中,然后再打开该数据库文件。复制的基本方法是使用getResources().openRawResource方法获得res\raw目录中资源的InputStream对象,然后将该InputStream对象中的数据写入其他的目录中相应文件中。在Android SDK中可以使用SQLiteDatabase.openOrCreateDatabase方法来打开任意目录中的SQLite数据库文件。
3.如果在AutoCompleteTextView组件中输入两个及以上字母时显示以所输入字符串开头的所有单词列表?
解答:AutoCompleteTextView所使用的Adapter是一个自定义的Adapter类,要注意的是,不能将整个数据库中的单词都查出,然后生成一个Adapter对象再使用setAdapter方法来设置AutoCompleteTextView组件的Adapter对象。AutoCompleteTextView组件不会为我们筛选以某个字符串开头的单词。这些工作需要开发人员通过编码来实现。基本思路是在AutoCompleteTextView类的afterTextChanged事件中监视AutoCompleteTextView组件中字符的输入情况,每当输入一个字符时就生成一个Adapter对象,然后将新生成的Adapter对象与AutoCompleteTextView关联。显示以输入字符串开头的单词列表的效果.
在本文实现的英文词典中使用openDatabase方法来打开数据库文件(该文件在SD卡的dictionary目录中,因此,要想运行本文实现的英文词典,需要在手机或模拟器中需要安装SD卡)。如果该文件不存在,系统会自动创建/sdcard/dictionary目录,并将res\raw目录中的dictionary.db文件复制到/sdcard/dictionary目录中。openDatabase方法的实现代码如下:
private SQLiteDatabase openDatabase()
{
try
{
// 获得dictionary.db文件的绝对路径
String databaseFilename \= DATABASE\_PATH + "/" + DATABASE\_FILENAME;
File dir \= new File(DATABASE\_PATH);
// 如果/sdcard/dictionary目录中存在,创建这个目录
if (!dir.exists())
dir.mkdir();
// 如果在/sdcard/dictionary目录中不存在
// dictionary.db文件,则从res\\raw目录中复制这个文件到
// SD卡的目录(/sdcard/dictionary)
if (!(new File(databaseFilename)).exists())
{
// 获得封装dictionary.db文件的InputStream对象
InputStream is \= getResources().openRawResource(R.raw.dictionary);
FileOutputStream fos \= new FileOutputStream(databaseFilename);
byte\[\] buffer = new
byte\[8192\];
int count = 0;
// 开始复制dictionary.db文件
while ((count = is.read(buffer)) > 0)
{
fos.write(buffer, 0, count);
}
fos.close();
is.close();
}
// 打开/sdcard/dictionary目录中的dictionary.db文件
SQLiteDatabase database \= SQLiteDatabase.openOrCreateDatabase(
databaseFilename, null);
return database;
}
catch (Exception e)
{
}
return
null;
}
在openDatabase方法中使用了几个常量,这些常量是在程序的主类(Main)中定义的,代码如下:
public
class Main extends Activity implements OnClickListener, TextWatcher
{
private
final String DATABASE\_PATH = android.os.Environment
.getExternalStorageDirectory().getAbsolutePath()
\+ "/dictionary";
private
final String DATABASE\_FILENAME = "dictionary.db";
... ...
}
查询单词
英文词典的核心就是查找英文单词的中文意思。在查找中文意思之前,首先需要使用openDatabase方法在Main类的onCreate方法中打开SQLite数据库,代码如下:database = openDatabase();其中database是在Main类中定义的SQLiteDatabase类型变量。然后在查找按钮的单击事件中添加如下的代码来查找英文单词,并显示中文意思。
public
void onClick(View view)
{
String sql \= "select chinese from t\_words where english=?";
Cursor cursor \= database.rawQuery(sql, new String\[\]
{ actvWord.getText().toString() });
String result \= "未找到该单词.";
//
如果查找单词,显示其中文信息
if (cursor.getCount() > 0)
{
//
必须使用moveToFirst方法将记录指针移动到第1条记录的位置
cursor.moveToFirst();
result \= cursor.getString(cursor.getColumnIndex("chinese"));
}
//显示查询结果对话框
new AlertDialog.Builder(this).setTitle("查询结果").setMessage(result)
.setPositiveButton("关闭", null).show();
}
讲到这里我们应该了解一个dictionary.db中的t_words表的结果,该表只有两个字段:english和chinese。分别表示单词的英文和中文描述。如果要获得单词的中文描述,只需要查找chinese字段即可。如onClick方法中的代码所示。查询单词的效果如图3所示。
如果显示以输入字符串开头的单词列表虽然到目前为止,我们的英文词典已经可以正常工作了,但为了方便读者使用,在本节将添加单词输入的自动提示功能。也就是说,如果读者在AutoCompleteTextView组件中输入单词的前几个字母,该组件就会自动列出数据库中所有以该字符串开头的单词。效果如图2所示。拥有这样的功能就可以使用户在只知道单词的前几个字母时也可以查找到相应的单词。由于AutoCompleteTextView组件使用了自定义的Adapter类,下面先给出这个自定义的Adapter类的完整代码。
public
class DictionaryAdapter extends CursorAdapter
{
private LayoutInflater layoutInflater;
@Override
public CharSequence convertToString(Cursor cursor)
{
return cursor == null ? "" : cursor.getString(cursor
.getColumnIndex("\_id"));
}
//
用于将\_id字段(也就是english字段)的值设置TextView组件的文本
//
view参数表示用于显示列表项的TextView组件
private
void setView(View view, Cursor cursor)
{
TextView tvWordItem \= (TextView) view;
tvWordItem.setText(cursor.getString(cursor.getColumnIndex("\_id")));
}
@Override
public
void bindView(View view, Context context, Cursor cursor)
{
setView(view, cursor);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent)
{
View view \= layoutInflater.inflate(R.layout.word\_list\_item, null);
setView(view, cursor);
return view;
}
public DictionaryAdapter(Context context, Cursor c, boolean autoRequery)
{
super(context, c, autoRequery);
//通过系统服务获得LayoutInflater对象
layoutInflater \= (LayoutInflater) context.getSystemService(Context.LAYOUT\_INFLATER\_SERVICE);
}
}
在编写DictionaryAdapter类时应注意如下3点:1. 为了将Cursor对象与AutoCompleteTextView组件绑定,DictionaryAdapter类必须从CursorAdapter类继承。2.由于CursorAdapter类中的convertToString方法直接返回了Cursor对象的地址,因此,在DictionaryAdapter类中必须覆盖convertToString方法,以返回当前选中的单词。CursorAdapter类中的convertToString方法的源代码。
public CharSequence convertToString(Cursor cursor)
{
//如果cursor不为null,返回Cursor对象的地址(cursor.toString())