Androidブラウザのアドレスバーでの履歴アクセス記録の自動ヒントの実現(AutoComplette TextView)

12862 ワード

この文章は必要なAndroid初心者のために、小さな機能を実現するために役立つことを目指しています。コードの品質は参考の意味がありません。文章の一番下のフォーマットもちょっと問題があります。
      現在はPCでも携帯電話でも、ブラウザのアドレスバーには履歴の自動提示機能が付いています。例えば、前に訪問したことがあります。http://www.qq.com次にqqを入力するか、www.qを入力すると(具体的な出発規則はカスタマイズできます)、http://www.qq.comアドレスバーの下にウィンドウを引くと自動的に表示されます。ユーザーが住所の入力作業を選択して完了するのに便利です。
      Androidでは、sdkによって提供されたAutoCompletTextViewと同様の機能を実現できます。もちろん、ここでは、ブラウザのアドレスヒントに限定されています。履歴はコントロールによって実現されます。コードによって具体的な実現過程を説明します。
      履歴の提示機能を実現するには、まず解決すべき問題は歴史記録の保存であり、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類を継承すれば、簡単にデータベースを作成できます。そして、OCreate()で必要なテーブルを作成します。コードは以下の通りです。
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) {}

}
      上層論理とデータベース操作の結合を解除するために、私達はクラスSuggationDBManageを作成することによって、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によって提供されるAutoComplette TextViewコントロールが必要です。このコントロールはAdapter方式を使用してヒントとなるデータをバインドしています。ListViewコントロールのようなものを使ったことがあれば、このような方式にはなじみがないはずですが、AutoComplet TextViewにとっては、バインディングされたAdapterはFilterableインターフェースを実現しなければなりません。キーワードのフィルタ機能はFilterというクラスで実現されますが、AutoCompletTextViewはFilterableインターフェースのget Filter()関数を呼び出し、具体的なFilterのインスタンスを得てフィルタリングを実行します。具体的なフィルタルールはFilterというクラスを引き継ぎ、Filter類のperformFiltering関数を再搭載してカスタマイズします。
      データベースへのアクセスはAsycTaskによって達成され、これはデータベースのquery操作が比較的に時間のかかる操作かもしれないことを考慮しているので、メインスレッドには適していない。AsycTaskを通じて、インタフェースの応答を失う問題を回避でき、データベースからデータを取得した後、notifyData SetChend()によってインタフェースを更新する。
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;
    }
}
SugsetionItem
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>
シンプル_リスト.item_for_automipete.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>