Android取消多次调用的异步任务

Posted

技术标签:

【中文标题】Android取消多次调用的异步任务【英文标题】:Android cancel async task called multi times 【发布时间】:2018-07-20 05:45:43 【问题描述】:

如何取消多次调用的异步任务,下面的代码将解释我的意思:

现在这是我的扩展 asyncTask 的类

private class sendMessage extends AsyncTask<Integer,Void,Long>

    public sendMessage() 
        super();
    

    @Override
    protected void onPreExecute() 
        super.onPreExecute();
    

    @Override
    protected void onProgressUpdate(Void... values) 
        super.onProgressUpdate(values);
    

    @Override
    protected void onPostExecute(Long aLong) 
        super.onPostExecute(aLong);
    

    @Override
    protected void onCancelled(Long aLong) 
        super.onCancelled(aLong);

        //task canceled will delete it from sqlite
        sqlite.deleteMessage(aLong);
    

    @Override
    protected void onCancelled() 
        super.onCancelled();
    

    @Override
    protected Long doInBackground(Integer... integers) 

          Long id sqlite.insertMessage("blabalbla");
    

现在在 android 中,我有一个用户列表视图,并且每个用户项都有按钮发送。 当用户点击发送它的显示加载在 listView 项目上意味着发送。

这将解释更多:

listview.setOnItemClickListener(new AdapterView.OnItemClickListener() 
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) 


        new sendMessage().excute(user_id);

        //sendMessage_task =  new sendMessage();
        //sendMessage_task.excute(user_id); 

        
       );

如果我对课程有参考,现在很容易取消这个 AsyncTask

sendMessage_task.cancel(true);

但是,如果用户单击 listView“发送按钮”中的许多项目,则引用将失败,因为它对一个对象的引用,当我取消任务时,它只会取消最后一个。

用户点击列表视图中的多个发送按钮

   sendMessage_task =  new sendMessage();
   sendMessage_task.excute(user_id); 

   sendMessage_task =  new sendMessage();
   sendMessage_task.excute(user_id); 

   sendMessage_task =  new sendMessage();
   sendMessage_task.excute(user_id); 

当我取消课程时,它只会取消最后一个

我只是想在 arrayList 或其他地方保存对象的引用 但我有活动轮换问题会将它们全部删除

【问题讨论】:

您想在何时何地取消任务非常模糊,但您自己说第一个问题是您没有存储对正在运行的任务的任何引用,因此没有什么可以取消的。解决这个问题,然后询问其余的问题。 @M.Prokhorov 取消将在再次单击发送按钮时执行 .. 是的,我不存储参考,因为它在 listView 中有许多项目,我将为其存储参考以及为什么我在那里发布问题,如果我完成了那个? 有几个项目的事实并不意味着你不应该存储任何东西。相反,您应该确定任务和列表项之间的关系,然后将该关系复制到存储中以运行任务。 【参考方案1】:

你的取消方法应该是这样的

private void cancel() 
    if (sendMessage_task == null) 
        return;
    
    sendMessage_task.cancel(true);
    sendMessage_task = null;

然后在每个“发送”事件上调用取消。

listview.setOnItemClickListener(new AdapterView.OnItemClickListener() 
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) 
    cancel();
    sendMessage_task =  new sendMessage();
    sendMessage_task.excute(user_id); 

    
   );

【讨论】:

好的,我知道这一点,但我说用户多次调用这个类并想再次取消它们,引用将仅用于最后一项,它不会全部取消【参考方案2】:

AsyncTask 实例只能执行一次。

你可以使用一个参考

private AsyncTask<Integer, Void, Long> task = null;

并在您的listener 取消前一个后多次重新创建它

在你的听众中:

if (task != null) 
    task.cancel(true);

task = new MyAsyncTask();
task.execute(...);

【讨论】:

好的,我知道这一点,但我说用户多次调用这个类并想再次取消它们,引用将仅用于最后一项,它不会全部取消 @smsmsmsm 你的意思是你想让很多AsyncTask 实例并行运行并且能够全部取消? 是的,就是这样......它是向用户转发消息的活动,您单击发送按钮并向许多用户发送消息也许您想取消您发送的一些消息,这就是想法【参考方案3】:

创建一个从用户IDAsyncTask的映射:

Map<Integer, AsyncTask> tasks = new HashMap<>(); // assuming user ID is Integer. Adjust if not.

当用户点击一个项目时,将用户的 ID 和你创建的 AsyncTask 放到地图上:tasks.put(userId, theNewlyCreatedTask)

当用户点击取消时,通过用户ID和cancel()找到对应的任务,如下所示:

AsyncTask myTask = tasks.get(userId);
if (myTask != null) 
    myTask.cancel();

【讨论】:

以上是关于Android取消多次调用的异步任务的主要内容,如果未能解决你的问题,请参考以下文章

取消没有实例的异步任务(Android)

如何取消 useEffect 清理函数中的所有订阅和异步任务?

浅谈android中异步加载之"取消异步加载"二

Android异步任务不会改变用户界面

如何在Android开发中用AsyncTask异步更新UI界面

23.FutureTask基本操作总结