当前位置: 代码迷 >> Android >> Android浏览器地址栏中历史采访记录的自动提示实现(AutoCompleteTextView)
  详细解决方案

Android浏览器地址栏中历史采访记录的自动提示实现(AutoCompleteTextView)

热度:386   发布时间:2016-05-01 14:59:33.0
Android浏览器地址栏中历史访问记录的自动提示实现(AutoCompleteTextView)

      此文旨在能帮助有需要的Android新手实现一个小小的功能,代码质量不具有任何参考意义,文章最下面的格式也有点小问题,搞了一会没搞定,放弃了。

      目前无论是PC上还是手机上,浏览器的地址栏都带有历史访问记录自动提示功能,例如之前访问过http://www.qq.com,那么当下次再次输入qq,或者www.q的时候(具体出发规则可定制),http://www.qq.com就会在地址栏下面以下拉窗口的形式自动给出提示,方便用户选择并完成地址的输入工作。

      在Android中,通过sdk提供的AutoCompleteTextView我们可以完成类似的功能,当然这里布局限于浏览器的地址提示,任何历史记录都可以通过该控件来实现,下面将通过代码来说明具体的实现过程。

      要实现历史记录的提示功能,首先要解决的问题就是历史记录的存储,Android中提供了几种存储方式,官方sdk文档中给出了详细的说明:http://developer.android.com/guide/topics/data/data-storage.html ,大概分析了一下,对于浏览器历史记录而言,SQLite应该是最合适的存储方式,Android原生浏览器也使用了SQLite的存储方式,因此本文也基于SQLite来保存历史记录。对于SQLite的介绍可以参考这篇文章:http://www.ibm.com/developerworks/cn/opensource/os-cn-sqlite/,下面就先来实现历史记录的存储部分。

      Android 提供了 SQLiteOpenHelper 来创建数据库,我们只要继承 SQLiteOpenHelper 类,就可以轻松的创建数据库,并在onCreate()中创建需要用到的表,代码如下:

import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;public class SuggestionDBHelper extends SQLiteOpenHelper{    private static final String DBNAME = "url.db";// 数据库名        public SuggestionDBHelper(Context context){        super(context, DBNAME, null, DATABASE_VERSION);    }    @Override    public void onCreate(SQLiteDatabase db) {        db.execSQL("CREATE TABLE IF NOT EXISTS history" +                  "(_id INTEGER PRIMARY KEY AUTOINCREMENT, url TEXT, title TEXT)");//创建history表,包含id,url和title字段    }    @Override    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}}

      为了解除上层逻辑和数据库操作之间的耦合,我们通过创建类SuggestionDBManage来封装url历史记录的添加和删除操作,这里主要实现了历史记录的insert和query函数,代码如下,代码不难理解:

import java.util.ArrayList;import java.util.List;import android.content.Context;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import com.tencent.test.SuggestionItem;public class SuggestionDBManage {    private SuggestionDBHelper mDateBaseHelper;    private SQLiteDatabase mDatabase;    public SuggestionDBManage(Context context) {        mDateBaseHelper = new SuggestionDBHelper(context);        mDatabase = mDateBaseHelper.getWritableDatabase();    }    public void insert(SuggestionItem urlitem) {        mDatabase.beginTransaction(); // 开始事务        try {            mDatabase.execSQL("INSERT INTO history VALUES(null, ?, ?)",                    new Object[] { urlitem.getUrl(), urlitem.getTitle() });            mDatabase.setTransactionSuccessful(); // 设置事务成功完成        } finally {            mDatabase.endTransaction(); // 结束事务        }    }    public List<SuggestionItem> query(String prefix) {        String like = prefix + "%";        List<SuggestionItem> values = new ArrayList<SuggestionItem>();        final String selection = "(url LIKE ? OR url LIKE ? OR url LIKE ? OR url LIKE ?)";        String[] selectionArgs = new String[4];        selectionArgs[0] = "http://" + like;        selectionArgs[1] = "http://www." + like;        selectionArgs[2] = "https://" + like;        selectionArgs[3] = "https://www." + like;        Cursor cursor = mDatabase.query("history", new String[] { "url", "title" }, selection,                selectionArgs, null, null, null);        cursor.moveToFirst();        for (int i = 0; i < cursor.getCount(); i++) {            String url = cursor.getString(0);            String title = cursor.getString(1);            values.add(new SuggestionItem(url, title));            cursor.moveToNext();        }        return values;    }        public void close(){        mDatabase.close();    }}

      为了实现历史记录的自动提示功能,我们需要借助Android提供的AutoCompleteTextView控件,该控件使用了Adapter方式来绑定用来提示的数据,用过类似ListView控件的话应该对这种方式不会陌生,然而对于AutoCompleteTextView来说,绑定的Adapter必须是实现了Filterable接口的Adapter,关键字的过滤功能是通过Filter这个类来实现的,而AutoCompleteTextView会调用Filterable接口的getFilter()函数,得到具体的Filter实例后执行过滤,具体的过滤规则是通过继承Filter这个类,并且重载Filter类的performFiltering函数来定制的。

      数据库的访问通过AsycTask来完成,这是考虑到数据库的query操作有可能是一个比较耗时的操作,因此不适合放到主线程中,通过AsycTask可以避免界面失去响应的问题,从数据库取得数据后通过notifyDataSetChanged()来更新界面,具体代码如下:

import java.util.ArrayList;import java.util.List;import android.content.Context;import android.os.AsyncTask;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.Filter;import android.widget.Filterable;import android.widget.TextView;import com.tencent.urldatabase.SuggestionDBManage;public class SuggestionAdapter extends BaseAdapter implements Filterable {    private Context context;    private SuggestionDBManage mDbManage;    private ArrayFilter mFilter;    private List<SuggestionItem> mFilterItems = new ArrayList<SuggestionItem>();// 过滤后的item    public SuggestionAdapter(Context context, SuggestionDBManage dbManage) {        this.context = context;        mDbManage = dbManage;    }    @Override    public Filter getFilter() {        if (mFilter == null) {            mFilter = new ArrayFilter();        }        return mFilter;    }    private class SuggestionAsyncTask extends AsyncTask<String, Void, List<SuggestionItem>>{        @Override        protected List<SuggestionItem> doInBackground(String... params) {            List<SuggestionItem> suggestionItems = mDbManage.query(params[0]);            return suggestionItems;        }        @Override        protected void onPostExecute(List<SuggestionItem> result) {            mFilterItems = result;            notifyDataSetChanged();            super.onPostExecute(result);        }                    }        private class ArrayFilter extends Filter {        @Override        protected FilterResults performFiltering(CharSequence prefix) {            String prefixString = prefix.toString().toLowerCase();            startSuggestionsAsync(prefixString);            return null;        }        private void startSuggestionsAsync(String prefixString) {            new SuggestionAsyncTask().execute(prefixString.toString());        }        @Override        protected void publishResults(CharSequence constraint,                FilterResults results) {}    }    @Override    public int getCount() {        return mFilterItems.size();    }    @Override    public Object getItem(int position) {        return mFilterItems.get(position);    }    @Override    public long getItemId(int position) {        return position;    }    @Override    public View getView(final int position, View convertView, ViewGroup parent) {        ViewHolder holder = null;        if (convertView == null) {            holder = new ViewHolder();            LayoutInflater inflater = (LayoutInflater) context                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);            convertView = inflater.inflate(                    R.layout.simple_list_item_for_autocomplete, null);            holder.url = (TextView) convertView.findViewById(R.id.url);            holder.title = (TextView) convertView.findViewById(R.id.title);            convertView.setTag(holder);        } else {            holder = (ViewHolder) convertView.getTag();        }        holder.url.setText(mFilterItems.get(position).getUrl());        holder.title.setText(mFilterItems.get(position).getTitle());        return convertView;    }    class ViewHolder {        TextView url;        TextView title;    }}
SuggestionItem
public class SuggestionItem {    private String mUrl;    private String mTitle;        public SuggestionItem(String url, String title) {        mUrl = url;        mTitle = title;    }    public String getUrl() {        return mUrl;    }    public String getTitle() {        return mTitle;    }}

MainActivity.java

import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.AutoCompleteTextView;import android.widget.Button;import android.widget.TextView;import com.tencent.urldatabase.SuggestionDBManage;public class MainActivity extends Activity implements OnItemClickListener{        private AutoCompleteTextView mAutoCompleteTextView;    private Button mSaveButton;    private SuggestionDBManage mUrlDBManage;    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        mUrlDBManage = new SuggestionDBManage(getApplicationContext());                mAutoCompleteTextView = (AutoCompleteTextView)findViewById(R.id.autotextview);        mAutoCompleteTextView.setText("");         mAutoCompleteTextView.setOnItemClickListener(this);                SuggestionAdapter adapter = new SuggestionAdapter(this, mUrlDBManage);        mAutoCompleteTextView.setAdapter(adapter);                mSaveButton = (Button)findViewById(R.id.savaurl);        mSaveButton.setOnClickListener(new OnClickListener() {            //这部分代码只是为了添加初始数据,只考虑http://开头的地址            @Override            public void onClick(View v) {                String prefix = "http://";                String urlString = mAutoCompleteTextView.getText().toString();                if (!urlString.startsWith(prefix)) {                    mUrlDBManage.insert(new SuggestionItem(prefix + urlString, "unknow"));                }                else {                    mUrlDBManage.insert(new SuggestionItem(urlString, "unknow"));                }            }        });    }    @Override    protected void onDestroy() {        mUrlDBManage.close();        super.onDestroy();    }     @Override    public void onItemClick(AdapterView<?> parent, View view, int position,            long id) {        TextView urlteTextView = (TextView)view.findViewById(R.id.title);        mAutoCompleteTextView.setText(urlteTextView.getText());    }}

main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="horizontal" >    <AutoCompleteTextView        android:id="@+id/autotextview"        android:layout_width="0dp"        android:layout_weight="1"        android:layout_height="wrap_content"        android:singleLine="true" />        <Button         android:id="@+id/savaurl"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="save"/></LinearLayout>

simple_list_item_for_autocomplete.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="horizontal" >        <TextView         android:id="@+id/url"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_weight="1"        android:textSize="16sp"/>        <TextView          android:id="@+id/title"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_weight="1"        android:gravity="right"        android:textSize="16sp"/></LinearLayout>
  相关解决方案