AutoCompleteTextView+SQLite实现自动检索
2013-03-28 10:37
435 查看
比如某些网页或搜索引擎会把用户搜索过的内容记录下来,当下次输入曾经搜索过的内容也会列出来。来个图,就明白了
保存记录有四种方法:Preferences,Files,Databases,Network。这里以Databases 为例,首先搭建个Provider(不会的童鞋可以参考sdk 里的demo:NotePad-记事本)。
先看看目录结构:
Message.java定义一些常量,数据库字段及Uri:
DatabaseHelper.java创建数据库及建表:
AutoProvider.java是继承ContentProvider对数据库进行插入,删除,查询,更新等操作,本例只需插入,查询,删除表几个操作:
上面3个文件就把Provider搭建好了,剩下要做的就是把记录集里以AutoCompleteTextView输入内容为头(startWith)的记录检索出来并显示出来。AutoCompleteTextView有个很重要的属性是android:completionThreshold,用于表明最小要敲入多少字符才开始显示list filter。AutoCompleteTextView要列出内容肯定要给它传一个数据源(记录集),就是通过setAdapter,这个适配器有个要求就是要实现android.widget.Filterable
接口,最简单的可以用ArrayAdapter ,如果用它的话,PopupListView样式不怎么好看,自定义适配器,自定义布局就好多了,请看:AutoCompleteAdapter.java(参考ArrayAdapter):
MainActivity.java做的事情是查询数据库,绑定数据源给AutoCompleteTextView:
过多的就不解释了。
源码下载地址:http://download.csdn.net/detail/zhouyuanjing/5187264
保存记录有四种方法:Preferences,Files,Databases,Network。这里以Databases 为例,首先搭建个Provider(不会的童鞋可以参考sdk 里的demo:NotePad-记事本)。
先看看目录结构:
Message.java定义一些常量,数据库字段及Uri:
package com.xyz.autocomplete.provider; import android.net.Uri; import android.provider.BaseColumns; public class Message { public static final String AUTHORITY = "com.xyz.auto"; public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.xyz.auto"; public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.xyz.auto"; public static final class Info implements BaseColumns { public static final String TABLE_NAME = "messages"; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/messages"); public static final Uri DELETE_ALL_URI = Uri.parse("content://" + AUTHORITY + "/messages/del/all"); public static final String MESSAGE_CONTENT = "message"; public static final String DEFAULT_SORT_ORDER = " message ASC "; } }
DatabaseHelper.java创建数据库及建表:
package com.xyz.autocomplete.provider; import android.content.Context; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; public class DatabaseHelper extends SQLiteOpenHelper { public static final String DB_NAME = "msg.db"; private static final int DB_VERSION = 1; public DatabaseHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); } @Override public void onCreate(SQLiteDatabase db) { // TODO Auto-generated method stub db.execSQL("CREATE TABLE " + Message.Info.TABLE_NAME + " (" + Message.Info._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + Message.Info.MESSAGE_CONTENT + " TEXT);"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub db.execSQL("DROP TABLE IF EXISTS " + Message.Info.TABLE_NAME); onCreate(db); } }
AutoProvider.java是继承ContentProvider对数据库进行插入,删除,查询,更新等操作,本例只需插入,查询,删除表几个操作:
package com.xyz.autocomplete.provider; import java.sql.SQLException; import java.util.HashMap; import com.xyz.autocomplete.R; import com.xyz.autocomplete.provider.Message.Info; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.text.TextUtils; import android.widget.Toast; public class AutoProvider extends ContentProvider { private static HashMap<String, String> sInfoProjectionMap; private static final int MESSAGE = 1; private static final int MESSAGE_ID = 2; private static final int DELETE_ALL = 3; private static final UriMatcher sUriMatcher; private DatabaseHelper mOpenHelper; static { sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); sUriMatcher.addURI(Message.AUTHORITY, Info.TABLE_NAME, MESSAGE); sUriMatcher.addURI(Message.AUTHORITY, Info.TABLE_NAME + "/#", MESSAGE_ID); sUriMatcher.addURI(Message.AUTHORITY, Info.TABLE_NAME + "/del/all", DELETE_ALL); sInfoProjectionMap = new HashMap<String, String>(); sInfoProjectionMap.put(Info._ID, Info._ID); sInfoProjectionMap.put(Info.MESSAGE_CONTENT, Info.MESSAGE_CONTENT); } ... @Override public boolean onCreate() { // TODO Auto-generated method stub mOpenHelper = new DatabaseHelper(getContext()); return true; } @Override public Uri insert(Uri uri, ContentValues values) { // TODO Auto-generated method stub if (sUriMatcher.match(uri) != MESSAGE) { throw new IllegalArgumentException("Provider insert() Unknown URI " + uri); } if (!values.containsKey(Info.MESSAGE_CONTENT)) { values.put(Info.MESSAGE_CONTENT, "default"); } SQLiteDatabase db = mOpenHelper.getWritableDatabase(); long rowId = db.insert(Info.TABLE_NAME, Info.TABLE_NAME, values); if (rowId <= 0) { try { throw new SQLException("Failed to insert row into " + uri); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } Uri retUri = ContentUris.withAppendedId(Info.CONTENT_URI, rowId); getContext().getContentResolver().notifyChange(retUri, null); Toast.makeText( getContext(), getContext().getString(R.string.insert_info) + values.getAsString(Info.MESSAGE_CONTENT), Toast.LENGTH_SHORT).show(); return retUri; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // TODO Auto-generated method stub SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); queryBuilder.setTables(Info.TABLE_NAME); switch (sUriMatcher.match(uri)) { case MESSAGE: queryBuilder.setProjectionMap(sInfoProjectionMap); break; case MESSAGE_ID: queryBuilder.setProjectionMap(sInfoProjectionMap); queryBuilder.appendWhere(Info._ID + " = " + uri.getPathSegments().get(1)); break; default: throw new IllegalArgumentException("Provider query() Unknown URI " + uri); } SQLiteDatabase db = mOpenHelper.getWritableDatabase(); Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder); cursor.setNotificationUri(getContext().getContentResolver(), uri); return cursor; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // TODO Auto-generated method stub SQLiteDatabase db = mOpenHelper.getWritableDatabase(); int count; switch (sUriMatcher.match(uri)) { ... case DELETE_ALL: db.execSQL("DROP TABLE IF EXISTS " + Info.TABLE_NAME); db.execSQL("CREATE TABLE " + Message.Info.TABLE_NAME + " (" + Message.Info._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + Message.Info.MESSAGE_CONTENT + " TEXT);"); return -1; default: throw new IllegalArgumentException("Provider delete() Unknown URI " + uri); } getContext().getContentResolver().notifyChange(uri, null); return count; } ... }
上面3个文件就把Provider搭建好了,剩下要做的就是把记录集里以AutoCompleteTextView输入内容为头(startWith)的记录检索出来并显示出来。AutoCompleteTextView有个很重要的属性是android:completionThreshold,用于表明最小要敲入多少字符才开始显示list filter。AutoCompleteTextView要列出内容肯定要给它传一个数据源(记录集),就是通过setAdapter,这个适配器有个要求就是要实现android.widget.Filterable
接口,最简单的可以用ArrayAdapter ,如果用它的话,PopupListView样式不怎么好看,自定义适配器,自定义布局就好多了,请看:AutoCompleteAdapter.java(参考ArrayAdapter):
package com.xyz.autocomplete; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.BaseAdapter; import android.widget.Filter; import android.widget.Filterable; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; public class AutoCompleteAdapter extends BaseAdapter implements Filterable { private int mLayoutId; private AutoFilter mFilter; private Context mContext; private List<String> mData; private List<String> mObjects; private Object mLock = new Object(); public AutoCompleteAdapter(Context ctx, int layout, ArrayList<String> data) { mContext = ctx; mLayoutId = layout; mData = data; mObjects = data; } @Override public int getCount() { // TODO Auto-generated method stub return mObjects.size() > 0 ? mObjects.size() + 1 : 0; } @Override public String getItem(int position) { // TODO Auto-generated method stub return position < getCount() - 1 ? mObjects.get(position) : mContext .getString(R.string.clear_info); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub ViewHolder holder = new ViewHolder(); if (convertView == null) { convertView = LayoutInflater.from(mContext).inflate( R.layout.auto_complete_item, null); holder.mShowText = (TextView) convertView.findViewById(R.id.item); holder.mIcon = (ImageView) convertView.findViewById(R.id.icon); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } if (position == 0) { convertView.setBackgroundResource(R.drawable.item_corner_top); holder.mShowText.setText(getItem(position)); holder.mIcon.setVisibility(View.GONE); } else if (position == getCount() - 1) { convertView.setBackgroundResource(R.drawable.item_corner_bottom); holder.mShowText.setText(mContext.getString(R.string.clear_info)); holder.mIcon.setVisibility(View.VISIBLE); } else { convertView.setBackgroundResource(R.drawable.item_corner_shape); holder.mShowText.setText(getItem(position)); holder.mIcon.setVisibility(View.GONE); } return convertView; } class ViewHolder { TextView mShowText; ImageView mIcon; } @Override public Filter getFilter() { // TODO Auto-generated method stub if (mFilter == null) { mFilter = new AutoFilter(); } return mFilter; } private class AutoFilter extends Filter { @Override protected FilterResults performFiltering(CharSequence constraint) { // TODO Auto-generated method stub FilterResults results = new FilterResults(); if (constraint == null || constraint.length() == 0) { ArrayList<String> list; synchronized (mLock) { list = new ArrayList<String>(mData); } results.values = list; results.count = list.size(); } else { String prefixString = constraint.toString().toLowerCase(); ArrayList<String> values; synchronized (mLock) { values = new ArrayList<String>(mData); } final int count = values.size(); final ArrayList<String> newValues = new ArrayList<String>(); for (int i = 0; i < count; i++) { final String value = values.get(i); final String valueText = value.toString().toLowerCase(); // First match against the whole, non-splitted value if (valueText.startsWith(prefixString)) { newValues.add(value); } else { final String[] words = valueText.split(" "); final int wordCount = words.length; // Start at index 0, in case valueText starts with // space(s) for (int k = 0; k < wordCount; k++) { if (words[k].startsWith(prefixString)) { newValues.add(value); break; } } } } results.values = newValues; results.count = newValues.size(); } return results; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { // TODO Auto-generated method stub mObjects = (List<String>) results.values; if (results.count > 0) { notifyDataSetChanged(); } else { notifyDataSetInvalidated(); } } } }
MainActivity.java做的事情是查询数据库,绑定数据源给AutoCompleteTextView:
package com.xyz.autocomplete; import java.util.ArrayList; import java.util.List; import com.xyz.autocomplete.provider.DatabaseHelper; import com.xyz.autocomplete.provider.Message.Info; import android.app.Activity; import android.content.AsyncQueryHandler; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.database.ContentObserver; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.text.TextUtils; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity implements OnClickListener, OnItemClickListener { private EditText mInputText; private Button mBtn; private AutoCompleteTextView mAutoCompleteView; private static final int QUERY_AUTO_TOKEN = 100; private ArrayList<String> mData = new ArrayList<String>(); private AutoCompleteAdapter mAutoAdaper = null; private DbChangeResolver mDbChangeResolver; private QueryHandler mQueryHandler = null; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mInputText = (EditText) findViewById(R.id.input); mBtn = (Button) findViewById(R.id.add); mBtn.setOnClickListener(this); mAutoCompleteView = (AutoCompleteTextView) findViewById(R.id.auto_complete); mAutoCompleteView.setOnItemClickListener(this); mAutoAdaper = new AutoCompleteAdapter(this, R.layout.auto_complete_item, mData); mAutoCompleteView.setAdapter(mAutoAdaper); mQueryHandler = new QueryHandler(getContentResolver()); startQuery(); mDbChangeResolver = new DbChangeResolver(new Handler()); getContentResolver().registerContentObserver( Info.CONTENT_URI, true, mDbChangeResolver); } private void startQuery() { mQueryHandler.startQuery(QUERY_AUTO_TOKEN, new Integer(0), Info.CONTENT_URI, new String[] { Info.MESSAGE_CONTENT }, null, null, Info.DEFAULT_SORT_ORDER); } @Override public void onClick(View v) { // TODO Auto-generated method stub if (!TextUtils.isEmpty(mInputText.getText().toString().trim())) { ContentValues cv = new ContentValues(1); cv.put(Info.MESSAGE_CONTENT, mInputText.getText().toString().trim()); getContentResolver().insert(Info.CONTENT_URI, cv); mInputText.getText().clear(); } else { Toast.makeText(this, getString(R.string.toast_info), Toast.LENGTH_LONG).show(); } } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // TODO Auto-generated method stub if (position == parent.getCount() - 1) { getContentResolver().delete(Info.DELETE_ALL_URI, null, null); mAutoCompleteView.getText().clear(); mData.clear(); Toast.makeText(this, "所有记录都清除啦", Toast.LENGTH_LONG).show(); } } private class QueryHandler extends AsyncQueryHandler { public QueryHandler(ContentResolver cr) { super(cr); // TODO Auto-generated constructor stub } @Override protected void onQueryComplete(int token, Object cookie, Cursor cursor) { if (QUERY_AUTO_TOKEN == token) { if (cursor == null) { return; } mData.clear(); while (cursor.moveToNext()) { mData.add(cursor.getString(cursor .getColumnIndexOrThrow(Info.MESSAGE_CONTENT))); } mAutoAdaper.notifyDataSetChanged(); } } } private class DbChangeResolver extends ContentObserver { private Handler mHandler; public DbChangeResolver(Handler handler) { super(handler); // TODO Auto-generated constructor stub mHandler = handler; } @Override public void onChange(boolean selfChange) { // TODO Auto-generated method stub super.onChange(selfChange); mHandler.removeCallbacks(mDataChangeRunnable); mHandler.postDelayed(mDataChangeRunnable, 300); } } private Runnable mDataChangeRunnable = new Runnable() { @Override public void run() { // TODO Auto-generated method stub startQuery(); } }; }
过多的就不解释了。
源码下载地址:http://download.csdn.net/detail/zhouyuanjing/5187264
相关文章推荐
- Android 系列 6.19 AutoCompleteTextView+SQLite实现自动检索
- AutoCompleteTextView 与sqlite绑定实现记住用户输入的内容并自动提示
- Android AutoCompleteTextView实现自动补全
- AutoCompleteTextView实现自动提示
- Android 01:AutoCompleteTextView-简单实现实现自动输入文本效果
- AutoCompleteTextView实现自动提示
- AutoCompleteTextView与自定义Adapter实现自动补全
- AutoCompleteTextView实现自动匹配输入内容
- 使用MultiAutoCompleteTextView实现自动匹配输入的内容
- 使用autoCompleteTextView以及MultiAutoCompleteTextView实现自动匹配输入内容
- 安卓控件——AutoCompleteTextView和MultiAutoCompleteTextView实现自动匹配输入的内容
- 使用AutoCompleteTextView和MultiAutoCompleteTextView实现输入自动匹配
- AutoCompleteTextView自动完成输入内容的控件
- AutoCompleteTextView输入汉字拼音首字母实现过滤提示(支持多音字)
- AutoCompleteTextView,MultiAutoCompleteTextView 自动补齐
- AutoCompleteTextView 自动完成
- Android 自动补全提示输入AutoCompleteTextView、 MultiAutoCompleteTextView
- AutoCompleteTextView(自动提示)
- 自动补全AutoCompleteTextView
- Android基础核心总结之二-----Spinner、AutoCompleteTextView(自动完成控件)