文档章节

Android Browser学习十二 UrlInputView(2) 网络联想数据的获取详细

SuShine
 SuShine
发布于 2014/09/10 21:58
字数 1091
阅读 211
收藏 1

前段时间介绍了大致获取搜索联想词的步骤, 这次我们介绍一下获取网络联想词的详细步骤, 我们知道 获取网络

联想词是通过SearchEngine实现的, 在浏览器中, 实现有两套方案:

  1. OpenSearchEngine会去定制的服务器获取搜索的联想词 

  2. DefaultSearchEngine 使用Android内部的SearchManager去query 联想列表


但是无论如何返回的数据是Cursor 并返回给SuggestCursor 

下面详细分析一下 首先是OpenSearchSearchEngine 的初始化: 初始化了 HttpClent

 public OpenSearchSearchEngine(Context context, SearchEngineInfo searchEngineInfo) {
        mSearchEngineInfo = searchEngineInfo;
        mHttpClient = AndroidHttpClient.newInstance(USER_AGENT);//设置了UA
        HttpParams params = mHttpClient.getParams(); 
        params.setLongParameter(HTTP_TIMEOUT, HTTP_TIMEOUT_MS);//设置超时
    }

在SlowFilterTask这个Task中开始query

class SlowFilterTask extends AsyncTask<CharSequence, Void, List<SuggestItem>> {

        @Override
        protected List<SuggestItem> doInBackground(CharSequence... params) {
            SuggestCursor cursor = new SuggestCursor();
            cursor.runQuery(params[0]);//开始query
            List<SuggestItem> results = new ArrayList<SuggestItem>();
            int count = cursor.getCount();//遍历Cursor中的各个数据
            for (int i = 0; i < count; i++) {
                results.add(cursor.getItem());
                cursor.moveToNext();
            }
            cursor.close();
            return results;
        }

        @Override
        protected void onPostExecute(List<SuggestItem> items) {
            mSuggestResults = items;
            mMixedResults = buildSuggestionResults();//获取数据成功了把数据混合然后更新UI
            notifyDataSetChanged();
        }
    }

在SuggestCursor的runQuery中调用 SearchEngine  的 getSuggestions函数

 /**
     * Queries for a given search term and returns a cursor containing
     * suggestions ordered by best match.
     */
    public Cursor getSuggestions(Context context, String query) {
        if (TextUtils.isEmpty(query)) {
            return null;
        }
        if (!isNetworkConnected(context)) {//检查网络是否ok
            Log.i(TAG, "Not connected to network.");
            return null;
        }

        String suggestUri = mSearchEngineInfo.getSuggestUriForQuery(query); //从什么搜索引擎搜索联想词
        if (TextUtils.isEmpty(suggestUri)) {
            // No suggest URI available for this engine
            return null;
        }

        try {
            String content = readUrl(suggestUri); //从网络获取联想词
            if (content == null) return null;
            /* The data format is a JSON array with items being regular strings or JSON arrays
             * themselves. We are interested in the second and third elements, both of which
             * should be JSON arrays. The second element/array contains the suggestions and the
             * third element contains the descriptions. Some search engines don't support
             * suggestion descriptions so the third element is optional.
             */
            JSONArray results = new JSONArray(content); //返回的是Json
            JSONArray suggestions = results.getJSONArray(1);
            JSONArray descriptions = null;
            if (results.length() > 2) {
                descriptions = results.getJSONArray(2);
                // Some search engines given an empty array "[]" for descriptions instead of
                // not including it in the response.
                if (descriptions.length() == 0) {
                    descriptions = null;
                }
            }
            return new SuggestionsCursor(suggestions, descriptions); //返回这个Json
        } catch (JSONException e) {
            Log.w(TAG, "Error", e);
        }
        return null;
    }

从网络获取数据代码

 /**
     * Executes a GET request and returns the response content.
     *
     * @param url Request URI.
     * @return The response content. This is the empty string if the response
     *         contained no content.
     */
    public String readUrl(String url) {
        try {
            HttpGet method = new HttpGet(url);
            HttpResponse response = mHttpClient.execute(method);
            if (response.getStatusLine().getStatusCode() == 200) {
                return EntityUtils.toString(response.getEntity());
            } else {
                Log.i(TAG, "Suggestion request failed");
                return null;
            }
        } catch (IOException e) {
            Log.w(TAG, "Error", e);
            return null;
        }
    }


SuggestionsCursor 继承自AbstractCursor 也是一个Cursor了

private static class SuggestionsCursor extends AbstractCursor {

        private final JSONArray mSuggestions;

        private final JSONArray mDescriptions;

        public SuggestionsCursor(JSONArray suggestions, JSONArray descriptions) {
            mSuggestions = suggestions;
            mDescriptions = descriptions;
        }

        @Override
        public int getCount() { //用来配合 moveToNext
            return mSuggestions.length();
        }

        @Override
        public String[] getColumnNames() {
            return (mDescriptions != null ? COLUMNS : COLUMNS_WITHOUT_DESCRIPTION);
        }

        @Override
        public String getString(int column) { 
            if (mPos != -1) {
                if ((column == COLUMN_INDEX_QUERY) || (column == COLUMN_INDEX_TEXT_1)) {
                    try {
                        return mSuggestions.getString(mPos);
                    } catch (JSONException e) {
                        Log.w(TAG, "Error", e);
                    }
                } else if (column == COLUMN_INDEX_TEXT_2) {
                    try {
                        return mDescriptions.getString(mPos);
                    } catch (JSONException e) {
                        Log.w(TAG, "Error", e);
                    }
                } else if (column == COLUMN_INDEX_ICON) {
                    return String.valueOf(R.drawable.magnifying_glass);
                }
            }
            return null;
        }

        @Override
        public double getDouble(int column) {
            throw new UnsupportedOperationException();
        }

        @Override
        public float getFloat(int column) {
            throw new UnsupportedOperationException();
        }

        @Override
        public int getInt(int column) {
            throw new UnsupportedOperationException();
        }

        @Override
        public long getLong(int column) {
            if (column == COLUMN_INDEX_ID) {
                return mPos;        // use row# as the _Id
            }
            throw new UnsupportedOperationException();
        }

        @Override
        public short getShort(int column) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean isNull(int column) {
            throw new UnsupportedOperationException();
        }
    }

这里废话一句AbstractCursor重要的函数 moveToFirst是如何使用getCount的 在AbstractCursor.java中

参考代码 http://code.taobao.org/p/cnandroiddocs/src/trunk/core/java/android/database/AbstractCursor.java

 public final boolean moveToPosition(int position) {        // Make sure position isn't past the end of the cursor
        final int count = getCount();        if (position >= count) {
            mPos = count;            return false;
        }        // Make sure position isn't before the beginning of the cursor
        if (position < 0) {
            mPos = -1;            return false;
        }        // Check for no-op moves, and skip the rest of the work for them
        if (position == mPos) {            return true;
        }        boolean result = onMove(mPos, position);        if (result == false) {
            mPos = -1;
        } else {
            mPos = position;            if (mRowIdColumnIndex != -1) {
                mCurrentRowID = Long.valueOf(getLong(mRowIdColumnIndex));
            }
        }        return result;
    }    @Override
    public void fillWindow(int position, CursorWindow window) {
        DatabaseUtils.cursorFillWindow(this, position, window);
    }    public final boolean move(int offset) {        return moveToPosition(mPos + offset);
    }    public final boolean moveToFirst() {        return moveToPosition(0);
    }

既然返回了SuggestCursor SuggestionAdapter就可以拿到Cursor进行 数据的读取了

 class SuggestCursor extends CursorSource {

        @Override
        public SuggestItem getItem() {//读取SuggestionsCursor中的数据
            if (mCursor != null) {
                String title = mCursor.getString( 
                        mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1));
                String text2 = mCursor.getString(
                        mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2));
                String url = mCursor.getString(
                        mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2_URL));
                String uri = mCursor.getString(
                        mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_DATA));
                int type = (TextUtils.isEmpty(url)) ? TYPE_SUGGEST : TYPE_SUGGEST_URL;
                SuggestItem item = new SuggestItem(title, url, type);
                item.extra = mCursor.getString(
                        mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA));
                return item;
            }
            return null;
        }

        @Override
        public void runQuery(CharSequence constraint) {
            if (mCursor != null) {
                mCursor.close();
            }
            //这里拿到的是OpenSearchSearchEngine对象,后面在分析
            SearchEngine searchEngine = mSettings.getSearchEngine();
            if (!TextUtils.isEmpty(constraint)) {
                if (searchEngine != null && searchEngine.supportsSuggestions()) {
                	//最后拿到的是json 然后返回一个cursor对象 操作json用来做混合 联想词 处理
                	//json居然可以这样用! 自定义Cursor , Cursor不仅仅可以用来存取数据库数据
                    mCursor = searchEngine.getSuggestions(mContext, constraint.toString());
                    if (mCursor != null) {
                        mCursor.moveToFirst(); 
                    }
                }
            } else {
                if (searchEngine.wantsEmptyQuery()) {
                    mCursor = searchEngine.getSuggestions(mContext, "");
                }
                mCursor = null;
            }
        }

    }



© 著作权归作者所有

SuShine
粉丝 128
博文 591
码字总数 158440
作品 0
朝阳
后端工程师
私信 提问
Android实战经验之图像处理及特效处理的集锦(总结版)

1 Android学习笔记进阶之在图片上涂鸦(能清屏) 2 Android学习笔记之详细讲解画圆角图片 3 Android学习笔记进阶20之得到图片的缩略图 4 Android学习笔记进阶19之给图片加边框 5 Android学习笔...

xiaosi
2012/03/12
40.1K
25
Android Browser学习〇 为什么要学习Android Browser代码

Browser的代码总算是看的差不多了,但是给我最大的感觉还是,乱.可能是我能力不够?但是说实话却是乱,结构混乱,感觉和OSC客户端的代码差距不少.感觉是一个哥们信手敲出来的,前期没什么规划什么的...

SuShine
2014/02/08
1K
0
Android RxJava: 这是一份全面的 操作符 使用汇总 (含详细实例讲解)

前言 ,由于其基于事件流的链式调用、逻辑简洁 & 使用简单的特点,深受各大 开发者的欢迎。 如果还不了解RxJava,请看文章:Android:这是一篇 清晰 & 易懂的Rxjava 入门教程 如此受欢迎的原...

Carson_Ho
2018/05/31
0
0
Android Browser学习二 BrowserActivity 的初始化 --其他重要模块

BrowserActivity 是浏览器的核心Activity了, 是浏览器的入口, 但是他里面并没有出来很多复杂的逻辑, 只是实现一些android 系统对activity的回调. 这些逻辑交给了Controller来处理, 就让我们一...

SuShine
2014/02/08
5.4K
0
CSDN日报19035——流浪地球 春节十二响程序开源代码

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/blogdevteam/article/details/88188905 游戏开发 | 【流浪地球】春节十二响程序开源代码 作者:刺客五六柒 前...

CSDN官方博客
03/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周六乱弹 —— 早上儿子问我他是怎么来的

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @凉小生 :#今日歌曲推荐# 少点戾气,愿你和这个世界温柔以待。中岛美嘉的单曲《僕が死のうと思ったのは (曾经我也想过一了百了)》 《僕が死の...

小小编辑
今天
2.2K
14
Excption与Error包结构,OOM 你遇到过哪些情况,SOF 你遇到过哪些情况

Throwable 是 Java 中所有错误与异常的超类,Throwable 包含两个子类,Error 与 Exception 。用于指示发生了异常情况。 Java 抛出的 Throwable 可以分成三种类型。 被检查异常(checked Exc...

Garphy
今天
38
0
计算机实现原理专题--二进制减法器(二)

在计算机实现原理专题--二进制减法器(一)中说明了基本原理,现准备说明如何来实现。 首先第一步255-b运算相当于对b进行按位取反,因此可将8个非门组成如下图的形式: 由于每次做减法时,我...

FAT_mt
昨天
40
0
好程序员大数据学习路线分享函数+map映射+元祖

好程序员大数据学习路线分享函数+map映射+元祖,大数据各个平台上的语言实现 hadoop 由java实现,2003年至今,三大块:数据处理,数据存储,数据计算 存储: hbase --> 数据成表 处理: hive --> 数...

好程序员官方
昨天
61
0
tabel 中含有复选框的列 数据理解

1、el-ui中实现某一列为复选框 实现多选非常简单: 手动添加一个el-table-column,设type属性为selction即可; 2、@selection-change事件:选项发生勾选状态变化时触发该事件 <el-table @sel...

everthing
昨天
21
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部