Android:基于服务器响应实现应用程序搜索建议



我需要在我的Android应用程序中构建搜索功能,该应用依赖于服务器的JSON响应。用户将在ActionBar中的搜索视图中输入搜索查询。根据用户类型的内容,将对服务器进行查询,并且服务器返回的响应应显示为下拉建议。我应该怎么做。根据我阅读的文档,我需要实现内容提供商。实施应用程序搜索的最整洁方法是什么?

请参阅我为Edittext实施的以下代码。您也可以做这样的事情:

private ArrayList<JSONObject> mRightListOverlapData, mRightTempData;
mEdit_Search.addTextChangedListener(new TextWatcher() {
        @Override
        public void onTextChanged(CharSequence s, int start, int before,
                int count) {

        }
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {
            // TODO Auto-generated method stub
        }
        @Override
        public void afterTextChanged(Editable s) {
            // TODO Auto-generated method stub
            mRightListOverlapData.clear();
            String searchTag = mEdit_Search.getText().toString();
            if (searchTag == null || searchTag.equals("")) {

                mRightTempData.clear();
                mOverlapAdapter.notifyDataSetChanged();
            } else if (searchTag.length() == 1) {
                    mRightListOverlapData.addAll(mRightTempData);

                    mOverlapAdapter.notifyDataSetChanged();
                } else {
                    **startServiceForSearchSuggestion(searchTag);**
                }

            } else {
                try {
                    if (mRightTempData.size() > 0) {
                        for (int i = 0; i < mRightTempData.size(); i++) {
                            if (mRightTempData.get(i)
                                    .getString("search_text").toLowerCase()
                                    .startsWith(searchTag.toLowerCase())) {
                                mRightListOverlapData.add(mRightTempData
                                        .get(i));
                            }
                        }
                        if (mRightListOverlapData.size() == 0) {
                            JSONObject noData = new JSONObject();
                            noData.put("search_text", "No Data");
                            mRightListOverlapData.add(noData);
                        }
                    }
                    mOverlapAdapter.notifyDataSetChanged();
                } catch (JSONException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    });

当用户输入Edittext。然后将所有响应保存到temparray中,当用户输入另一个字符时,它将调用Web服务,然后将所有响应保存到temparray中。方法starterviceforsearchsuggestion()为:

private void startServiceForSearchSuggestion(String search_tag) {
    if (!Utils.isNetworkAvailable(getBaseContext())) {
        Toast.makeText(getBaseContext(), "No Network Available",
                Toast.LENGTH_SHORT).show();
    } else {
        Intent intent1 = new Intent(this, WebService.class);
        intent1.putExtra(METHOD, GET_SEARCH_SUGGESTION);
        intent1.putExtra("search_tag", search_tag);
        startService(intent1);
    }
}

它将启动Web服务以从服务器获得响应。服务类是:

 public class WebService extends Service implements WebServiceConstants {
    private AppPreferences mPrefs;
    private static String TAG_WEB_SERVICE = "WebService";
    private static String DEVICE_TYPE = "android";
    private static String MESSAGE_CENTER = "gcm";
    private static String URL_JSON = "YOUR_URL";
    private Context mContext;
    private int METHOD_NAME = 1;
    private String mSearch_Tag = "";
    private DBQuery mDBQuery;
    public static boolean is_Service_Running = false;
    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        mContext = this;
        mPrefs = new AppPreferences(mContext);
        mDBQuery = new DBQuery(mContext);
    }
    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public void onStart(Intent intent, int startId) {
        // TODO Auto-generated method stub
        try {
            METHOD_NAME = intent.getIntExtra(METHOD, 1);
                mSearch_Tag = intent.getStringExtra("search_tag");
            LoadDataFromServer data = new LoadDataFromServer();
            data.execute();
        } catch (NullPointerException e) {
            // TODO: handle exception
        }
        super.onStart(intent, startId);
    }
public class LoadDataFromServer extends AsyncTask<Void, Void, Void> {
        JSONObject response;
        @Override
        protected Void doInBackground(Void... params) {
            // TODO Auto-generated method stub
            JSONObject root = getJsonHeader();
            switch (METHOD_NAME) {

            case GET_SEARCH_SUGGESTION:
                response = getResponse(yourJsonRequestObject);
                break;
            }
            return null;
        }
        @Override
        protected void onPostExecute(Void result) {
            // TODO Auto-generated method stub
            try {
                switch (METHOD_NAME) {

                case GET_SEARCH_SUGGESTION:
                    Log.v(TAG_WEB_SERVICE,
                            "Response = GET_SEARCH_SUGGESTION : "
                                    + response.toString());
                    sendBroadcast(new Intent(METHOD_GET_SEARCH_SUGGESTION)
                            .putExtra("Response", response.toString()));
                    break;
                default:
                    break;
                }
            } catch (NullPointerException e) {
                // TODO: handle exception
            }
        }
    }
    }

OnPostExecute方法,您必须将广播发送到您的活动,并且对此广播的态度您可以将JSON数据保存到arraylist中。例如:

private BroadcastReceiver mReceiverSearchSuggestion = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // TODO Auto-generated method stub
            JSONObject root;
            try {
                root = new JSONObject(intent.getStringExtra("Response"));
                setSearchSuggestions(root);
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };

方法:

1。

private JSONObject getResponse(JSONObject obj) {
        // Create a new HttpClient and Post Header
        HttpClient httpclient = new DefaultHttpClient();
        HttpParams myParams = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout(myParams, 10000);
        HttpConnectionParams.setSoTimeout(myParams, 10000);
        String temp = "";
        try {
            HttpPost httppost = new HttpPost(URL_JSON);
            httppost.setHeader("Content-type", "application/json");
            StringEntity se = new StringEntity(obj.toString());
            se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,
                    "application/json"));
            httppost.setEntity(se);
            HttpResponse response = httpclient.execute(httppost);
            temp = EntityUtils.toString(response.getEntity());
            Log.v(TAG_WEB_SERVICE, "Temp = " + temp);
            if (temp == null || temp.trim().equals("")) {
            } else {
                return new JSONObject(temp);
            }
        } catch (ClientProtocolException e) {
        } catch (IOException e) {
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

2。

private void setSearchSuggestions(JSONObject root) {
        // TODO Auto-generated method stub
        try {
            JSONObject search_suggestion = root
                    .getJSONObject(METHOD_GET_SEARCH_SUGGESTION);
            if (search_suggestion.getString("response_type").equalsIgnoreCase(
                    "success")) {
                if (search_suggestion.has("data")) {
                    mRightTempData.clear();
                    mRightListOverlapData.clear();
                    JSONArray data = search_suggestion.getJSONArray("data");
                    for (int i = 0; i < data.length(); i++) {
                        JSONObject value = data.getJSONObject(i);
                        mRightTempData.add(value);
                    }
                } else {
                    Toast.makeText(getBaseContext(),
                            "No data related to search", Toast.LENGTH_SHORT)
                            .show();
                }
            } else {
                Toast.makeText(getBaseContext(),
                        "Search Suggestion : Type Failure", Toast.LENGTH_SHORT)
                        .show();
            }

    }

我已经将适配器设置为JSON对象的ArrayList:

        mOverlapAdapter = new RightOverlapAdapter(getBaseContext(),
            mRightListOverlapData);
    mDListRightOverLap.setAdapter(mOverlapAdapter);

您可以将带有指定标签的Jonobject的ArrayList直接读取数据中的getView方法。

您需要在这样的清单中定义此服务:

 <service android:name="com.your.package.WebService" />

希望它对您有帮助。

您可以自定义AutoCompleteTextView的适配器。

...
getInput = (AutoCompleteTextView) rootView
                .findViewById(R.id.translate_word);
getInput.setAdapter(new AutoCompleteAdapter(mContext));
...

自动填充类班级

public class AutoCompleteAdapter extends ArrayAdapter<AutoCompleteItem> {
    protected static final String TAG = "AutoCompleteAdapter";
    private Context mContext; 
    private LayoutInflater vi; 
    private List<AutoCompleteItem> suggestions;
    public AutoCompleteAdapter(Context context) {
        super(context, R.layout.autocomplete_item);
        this.mContext = context;
        vi = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        suggestions = new ArrayList<AutoCompleteItem>();
    }
    @Override
    public int getCount() {
        return suggestions.size();
    }
    @Override
    public AutoCompleteItem getItem(int index) {
        return suggestions.get(index);
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView; 
        final AutoCompleteItem i = suggestions.get(position); 
        if (i != null) {
            AutoCompleteItem aci = (AutoCompleteItem)i; 
            v = vi.inflate(R.layout.autocomplete_item, null); 
            final TextView txtWord = (TextView)v.findViewById(R.id.word);
            if (txtWord != null) { 
                txtWord.setText(aci.getWord());
            }
            final TextView txtLang = (TextView)v.findViewById(R.id.lang);
            if (txtLang != null) {
                if (aci.getLang() != null && !aci.getLang().equals(""))
                    txtLang.setText("[" + aci.getLang().toUpperCase() + "]");
            }
            final TextView txtConj = (TextView)v.findViewById(R.id.conj);
            if (txtConj != null) { 
                txtConj.setText(aci.getConj());
                txtConj.setTag(i); 
                txtConj.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        AutoCompleteItem autoCompleteItem = (AutoCompleteItem)v.getTag(); 
                        String lang = autoCompleteItem.getLang(); 
                        // v.getParent().
                        String word = autoCompleteItem.getWord(); 
                    }
                }); 
            }
        }
        return v; 
    }

    @Override
    public Filter getFilter() {
        Filter myFilter = new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                FilterResults filterResults = new FilterResults();
                if (constraint != null && !constraint.toString().equalsIgnoreCase(sWord) && constraint.toString().length() >= 2) {
                    AutoCompleteParse acp = new AutoCompleteParse();
                    // A class that queries a web API, parses the data and
                    // returns an ArrayList<AutoCompleteItem>
                    List<AutoCompleteItem> new_suggestions =acp.getAutoComplete(mContext, constraint.toString());
                    suggestions.clear();
                    for (int i=0;i<new_suggestions.size();i++) {
                        suggestions.add(new_suggestions.get(i));
                    }
                    if (suggestions.size() > 0) sWord = constraint.toString(); 
                    // Now assign the values and count to the FilterResults
                    // object
                    filterResults.values = suggestions;
                    filterResults.count = suggestions.size();
                }
                return filterResults;
            }
            @Override
            protected void publishResults(CharSequence contraint,
                    FilterResults results) {
                if (contraint != null && !contraint.toString().equalsIgnoreCase(sWord) && contraint.toString().length() >= 2 
                        && results != null && results.count > 0) {
                    notifyDataSetChanged();
                } else {
                    notifyDataSetInvalidated();
                }
            }
        };
        return myFilter;
    }
}

自动完成类

public class AutoCompleteParse {
Context mContext; 
public AutoCompleteParse() {
}
public List<AutoCompleteItem> getAutoComplete(Context context, String sWord) {
    this.mContext = context;

    ...
    List<AutoCompleteItem> ListData = new ArrayList<AutoCompleteItem>();
    try {
        URL acUrl = new URL(autoCompleteUrl);
        URLConnection acConn = acUrl.openConnection();
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                acConn.getInputStream()));
        String line = reader.readLine();
        do {
        ...
        } while (line != null);
    } catch (Exception e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    return ListData;
}

最新更新