首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Android停止启动AsyncTask

Android停止启动AsyncTask
EN

Stack Overflow用户
提问于 2013-10-11 18:40:31
回答 1查看 533关注 0票数 0

我有一个AsyncTask (AddressUpdaterTask),它从AutoCompleteTextView获取文本,解析它,然后显示一个下拉地址列表,就像在谷歌地图中键入地址一样。每次用户键入字符时,都会执行新的AddressUpdaterTask。我的问题是,这是没有效率的,因为当用户开始键入时,如果输入速度足够快,就会执行一个新的AsyncTask,而之前的一个可能还没有完成执行。

所以我做了这个:

代码语言:javascript
运行
复制
AddressUpdaterTask addressUpdaterTask = new AddressUpdaterTask();

当addressUpdaterTask是全局的,当用户输入一个字符时,我会这样做:

代码语言:javascript
运行
复制
addressUpdaterTask.cancel(true);
addressUpdaterTask.execute();

这样我就可以操作AddressUpdaterTask的一个实例。但这样做是行不通的:(我如何实现我想要的?

编辑:这是我的代码:

代码语言:javascript
运行
复制
public class RegisterDoctor extends Activity {

        .
        .
        .

    private AutoCompleteTextView addressField;
    private ArrayAdapter<String> adapter;
    private Filter filter;
    private List<SimpleAddress> simpleAddresses = new ArrayList<SimpleAddress>();
    private SimpleAddress currentAddress = null;
    AddressUpdaterTask addressUpdaterTask = new AddressUpdaterTask();



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.register_doctor);

        .
        .
        .


        //AutoCompleteTextView Creation
        addressField = (AutoCompleteTextView) findViewById(R.id.addressEditText);
        addressField.setThreshold(ADDRESS_TRESHOLD);
        addressField.setHint("Οδός Αριθμός, Περιοχή");
        filter = new Filter() {
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                adapter.notifyDataSetChanged();
            }

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                Log.i("FILTER_ACTION", "Filter:" + constraint);
                if (constraint != null && constraint.length() > ADDRESS_TRESHOLD) {
                    Log.i("FILTER_ACTION", "doing a search ..");
                    addressUpdaterTask.cancel(true);
                    addressUpdaterTask.execute();
                }
                return null;
            }
        };
        adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line) {
            public android.widget.Filter getFilter() {
                return filter;
            }
        };
        addressField.setAdapter(adapter);
        adapter.setNotifyOnChange(false);
        addressField.setOnItemClickListener(itemClicked);

        .
        .
        .

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }


    private AdapterView.OnItemClickListener itemClicked = new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View arg1, int pos, long id) {
            currentAddress = simpleAddresses.get(pos);
            Log.i("ITEM_CLICKED", simpleAddresses.get(pos).getFormatted_address());
        }
    };

        .
        .
        .

    public class AddressUpdaterTask extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            //adapter.clear();
        }


        @Override
        protected Void doInBackground(Void... voids) {
            try {
                simpleAddresses = new JsonHelper().getAddresses(addressField.getText().toString());
            } catch (NullPointerException e) {
            }
            return null;
        }
@Override
        protected void onPostExecute(Void aVoid) {
            int size = simpleAddresses.size();

            if (size > 0) {
                adapter.clear();
                for (int i = 0; i < size; i++) {
                    adapter.add(simpleAddresses.get(i).getFormatted_address());
                    Log.i("ADDRESS_ADDED", simpleAddresses.get(i).getFormatted_address());
                }
                adapter.notifyDataSetChanged();
                addressField.showDropDown();
            }
            super.onPostExecute(aVoid);
        }
    }
        .
        .
        .
}

编辑2:这是用户输入=> 6字符(我输入的阈值)的那一刻起的逻辑猫,AsyncTask可以执行:

代码语言:javascript
运行
复制
10-11 18:56:59.795    1465-1494/com.user.project I/FILTER_ACTION: Filter:panepi
10-11 18:57:02.695    1465-1494/com.user.project I/FILTER_ACTION: Filter:panepis
10-11 18:57:02.695    1465-1494/com.user.project I/FILTER_ACTION: doing a search ..
10-11 18:57:06.544    1465-1496/com.user.project I/FILTER_ACTION: Filter:panepist
10-11 18:57:06.544    1465-1496/com.user.project I/FILTER_ACTION: doing a search ..
10-11 18:57:06.555    1465-1496/com.user.project W/Filter: An exception occured during performFiltering()!
        java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)
        at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:578)
        at android.os.AsyncTask.execute(AsyncTask.java:534)
        at com.user.project.RegisterDoctor$2.performFiltering(RegisterDoctor.java:104)
        at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.os.HandlerThread.run(HandlerThread.java:60)
10-11 18:57:09.004    1465-1496/com.user.project I/FILTER_ACTION: Filter:panepisti
10-11 18:57:09.004    1465-1496/com.user.project I/FILTER_ACTION: doing a search ..
10-11 18:57:09.014    1465-1496/com.user.project W/Filter: An exception occured during performFiltering()!
        java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)
        at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:578)
        at android.os.AsyncTask.execute(AsyncTask.java:534)
        at com.user.project.RegisterDoctor$2.performFiltering(RegisterDoctor.java:104)
        at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.os.HandlerThread.run(HandlerThread.java:60)
10-11 18:57:09.904    1465-1496/com.user.project I/FILTER_ACTION: Filter:panepistim
10-11 18:57:09.904    1465-1496/com.user.project I/FILTER_ACTION: doing a search ..
10-11 18:57:09.914    1465-1496/com.user.project W/Filter: An exception occured during performFiltering()!
        java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)
        at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:578)
        at android.os.AsyncTask.execute(AsyncTask.java:534)
        at com.user.project.RegisterDoctor$2.performFiltering(RegisterDoctor.java:104)
        at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.os.HandlerThread.run(HandlerThread.java:60)
10-11 18:57:10.194    1465-1496/com.user.project I/FILTER_ACTION: Filter:panepistimi
10-11 18:57:10.194    1465-1496/com.user.project I/FILTER_ACTION: doing a search ..
10-11 18:57:10.194    1465-1496/com.user.project W/Filter: An exception occured during performFiltering()!
        java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)
        at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:578)
        at android.os.AsyncTask.execute(AsyncTask.java:534)
        at com.user.project.RegisterDoctor$2.performFiltering(RegisterDoctor.java:104)
        at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.os.HandlerThread.run(HandlerThread.java:60)
10-11 18:57:11.865    1465-1496/com.user.project I/FILTER_ACTION: Filter:panepistimio
10-11 18:57:11.865    1465-1496/com.user.project I/FILTER_ACTION: doing a search ..
10-11 18:57:11.954    1465-1496/com.user.project W/Filter: An exception occured during performFiltering()!
        java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)
        at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:578)
        at android.os.AsyncTask.execute(AsyncTask.java:534)
        at com.user.project.RegisterDoctor$2.performFiltering(RegisterDoctor.java:104)
        at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.os.HandlerThread.run(HandlerThread.java:60)
10-11 18:57:12.196    1465-1496/com.user.project I/FILTER_ACTION: Filter:panepistimiou
10-11 18:57:12.196    1465-1496/com.user.project I/FILTER_ACTION: doing a search ..
10-11 18:57:12.295    1465-1496/com.user.project W/Filter: An exception occured during performFiltering()!
        java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)
        at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:578)
        at android.os.AsyncTask.execute(AsyncTask.java:534)
        at com.user.project.RegisterDoctor$2.performFiltering(RegisterDoctor.java:104)
        at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.os.HandlerThread.run(HandlerThread.java:60)
10-11 18:57:14.795      404-966/com.android.inputmethod.latin E/ActivityThread: Failed to find provider info for com.android.inputmethod.latin.dictionarypack
10-11 18:57:14.805      404-966/com.android.inputmethod.latin E/BinaryDictionaryGetter: Could not find a dictionary pack
10-11 18:57:14.815    1465-1496/com.user.project I/FILTER_ACTION: Filter:panepistimiou
10-11 18:57:14.815    1465-1496/com.user.project I/FILTER_ACTION: doing a search ..
10-11 18:57:14.815    1465-1496/com.user.project W/Filter: An exception occured during performFiltering()!
        java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)
        at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:578)
        at android.os.AsyncTask.execute(AsyncTask.java:534)
        at com.user.project.RegisterDoctor$2.performFiltering(RegisterDoctor.java:104)
        at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.os.HandlerThread.run(HandlerThread.java:60)
EN

回答 1

Stack Overflow用户

发布于 2013-10-11 18:50:44

在实现自动完成时,通常会引入一些延迟,以便在不返回结果的情况下不会多次调用该服务。

尝试添加一个变量(可能是静态的),该变量跟踪用户何时输入第一个输入,并且只在经过一定时间(500-750 is相当常见)之后执行搜索。这是一个更好的UX,但并不能解决您最初的问题。

对于“双重执行”问题,只需在请求启动时将条件设置为true,在请求结束时设置为false,并且在设置变量时不允许启动另一个请求。

就像这样:

代码语言:javascript
运行
复制
bool requestInProgress = false;

...

@Override
protected void onPreExecute() {
    super.onPreExecute();
    requestInProgress = true;
}

protected void onPostExecute(Void aVoid) {
    int size = simpleAddresses.size();

    if (size > 0) {
        adapter.clear();
        for (int i = 0; i < size; i++) {
            adapter.add(simpleAddresses.get(i).getFormatted_address());
            Log.i("ADDRESS_ADDED", simpleAddresses.get(i).getFormatted_address());
        }
        adapter.notifyDataSetChanged();
        addressField.showDropDown();
    }
    super.onPostExecute(aVoid);
    requestInProgress = false;
}

上面..。

代码语言:javascript
运行
复制
@Override
protected FilterResults performFiltering(CharSequence constraint) {
    Log.i("FILTER_ACTION", "Filter:" + constraint);
    if (constraint != null && constraint.length() > ADDRESS_TRESHOLD 
           && !requestInProgress) {
        Log.i("FILTER_ACTION", "doing a search ..");
        addressUpdaterTask.cancel(true);
        addressUpdaterTask.execute();
    }
    return null;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19325090

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档