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

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

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

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

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


213457_IBfb_259459.png

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

214610_TGTd_259459.jpg

下面详细分析一下 首先是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;
            }
        }

    }



转载于:https://my.oschina.net/sfshine/blog/312199

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值