自动搜索为用户类型自动搜索、类型、用户

2023-09-06 00:27:29 作者:淡看云卷云舒

我有一个活动,其中在一个EditText用户类型,点击搜索按钮,以及应用程序查询一个Web服务,并将结果在ListView。

我想用搜索按钮做了。

很显然,我不希望每个字符的用户类型击中Web服务。我想,当用户完成输入,只执行1 Web服务调用。

我实现这一目标的方法是像这样:

我有持有AsyncTask的一个成员变量。当在变化的EditText文本,该AsyncTask的火灾。内部doInBackground(),调用Thread.sleep()方法被击中。这种睡眠期间基本上是一个计时器等待如果用户键入别的看到的。睡眠通话结束后,调用Web服务,如果AsyncTask的还没有被取消而成。如果用户键入另一个字母,取消()被调用的AsyncTask的(以阻止被称为Web服务),成员变量持有的AsyncTask设置为空,并创建的AsyncTask的新实例。

我有几个问题在这里:我是不是内存泄露?这是在任何情况特别不好?我的理解可能不是最有效的,但我要去认真地减缓人的电话?是否有这样做的更好的办法?

 私人SearchTask mSearchTask = NULL;
 

...

  mSearchText.addTextChangedListener(新TextWatcher(){

        公共无效onTextChanged(CharSequence中,诠释开始,诠释之前,诠释计数){
            //自动生成方法存根
        }

        公共无效beforeTextChanged(CharSequence中,诠释开始,诠释计数,
                之后INT){
            //自动生成方法存根
        }

        公共无效afterTextChanged(编辑S){
                如果(S =空&安培;!&安培; s.length()大于0){
                    //停止任何当前的搜索线程
                    如果(mSearchTask =空&安培;!&安培;!mSearchTask.isCancelled()){
                        mSearchTask.cancel(假);
                    }


                        //搜索产品
                        SearchCriteria暴击=新SearchCriteria();
                        crit.strSearchWord = mSearchText.getText()的toString()修剪()。
                        mSearchTask = NULL;
                        mSearchTask =新SearchTask();
                        mSearchTask.execute(暴击);
                }
        }
    });
 

...

 私有类SearchTask扩展的AsyncTask< SearchCriteria,整型,布尔> {
    保护布尔doInBackground(SearchCriteria ... PARAMS){
        SearchCriteria暴击= NULL;
        如果(params.length大于0){
            暴击= PARAMS [0];

            如果(暴击!= NULL){
                尝试 {
                    视频下载(1000L);
                    如果(!isCancelled()){
                        //执行搜索
                        返回true;
                    }
                }
                赶上(例外五){
                }
            }
        }

        返回false;
    }

    保护无效onPostExecute(布尔成功){
        如果(成功= NULL和放大器;!&安培;成功==真){
            // 做一点事
        }
        其他 {
            //做别的事情
        }
    }
}
 
UClient下载 UBrowser v2.0.0.1580 官方版

解决方案

我会更倾向于推出以x毫秒的线程,并做检查的话,而不是立即在那里睡眠启动线程。

 专用处理器mMessageHandler =新的处理程序();

私人可运行mSearchRunnable =新的Runnable(){
        公共无效的run(){
           如果(!isCancelled()){
               //执行搜索
           }
        }
    };
 

那么你就可以在你把这个 afterTextChanged

  mMessageHandler.postDelayed(mSearchRunnable,1000);
 

如果用户输入的数据,你就可以取消该线程:

  mMessageHandler.removeCallbacks(mSearchRunnable);
 

I have an Activity where a user types in an EditText, hits a search button, and the app queries a web service and places the results in a ListView.

I'd like to do away with the search button.

Obviously I don't want every character the user types to hit the web service. I want to only execute 1 web service call when the user is finished typing.

The way I'm achieving this is like so:

I have a member variable which holds an AsyncTask. When the text in the EditText changes, the AsyncTask fires. Inside doInBackground(), a call to Thread.sleep() is hit. This sleep period is essentially a timer waiting to see if the user types anything else. After the sleep call, the call to the web service is made if the AsyncTask has not been cancelled. If the user types another letter, cancel() is called on the AsyncTask (to stop the web service from being called), the member variable holding the AsyncTask is set to null, and a new instance of the AsyncTask is created.

I have a few questions here: Am I leaking memory? Is this particularly bad in any way? I understand it may not be most efficient, but am I going to seriously slow down someone's phone? Is there a better way of doing this?

private SearchTask mSearchTask = null;

...

    mSearchText.addTextChangedListener(new TextWatcher() {

        public void onTextChanged(CharSequence s, int start, int before, int count) {
            // Auto-generated method stub
        }

        public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {
            // Auto-generated method stub
        }

        public void afterTextChanged(Editable s) {
                if (s != null && s.length() > 0) {
                    // stop any current search thread
                    if (mSearchTask != null && !mSearchTask.isCancelled()) {
                        mSearchTask.cancel(false);
                    }


                        // search for products
                        SearchCriteria crit = new SearchCriteria();
                        crit.strSearchWord = mSearchText.getText().toString().trim();
                        mSearchTask = null;
                        mSearchTask = new SearchTask();
                        mSearchTask.execute(crit);
                }
        }
    });

...

private class SearchTask extends AsyncTask<SearchCriteria, Integer, Boolean> {
    protected Boolean doInBackground(SearchCriteria... params) {
        SearchCriteria crit = null;
        if (params.length > 0) {
            crit = params[0];

            if (crit != null) {
                try {
                    Thread.sleep(1000L);
                    if (!isCancelled()) {
                        // perform search
                        return true;
                    }
                }
                catch(Exception e) {
                }
            }
        }

        return false;
    }

    protected void onPostExecute(Boolean success) {
        if (success != null && success == true) {
            // do something
        }
        else {
            // do something else
        }
    }   
}

解决方案

I would be more tempted to launch a thread in x milliseconds and do the check then, as opposed to launching the thread immediately with a sleep in there.

private Handler mMessageHandler = new Handler();

private Runnable mSearchRunnable = new Runnable() {
        public void run() {
           if (!isCancelled()) {
               // perform search
           }
        }
    };

then you can put this in you afterTextChanged:

mMessageHandler.postDelayed(mSearchRunnable, 1000);

you can then cancel the thread if the user enters more data with:

 mMessageHandler.removeCallbacks(mSearchRunnable);