【问题标题】:Detecting if a refresh button has been selected while AsyncTasks are still running在 AsyncTasks 仍在运行时检测是否选择了刷新按钮
【发布时间】:2012-04-21 17:07:47
【问题描述】:

我有一个 Android 应用程序,它使用列表活动来显示从互联网上提取的项目列表。我首先使用 AsyncTask 加载列表,该 Async 任务完成它调用不同的异步任务来开始加载与列表项一起出现的缩略图。我遇到的问题是用户可以访问他们可以随时按下的刷新按钮,当按下它时,整个项目列表将被删除并重新开始加载。如果发生这种情况,加载缩略图的异步任务可能仍在运行,然后可能会尝试将缩略图添加到不存在的列表项。我试过在列表上同步,使用一个布尔值,经过研究我意识到这不起作用。我还尝试使用静态原子布尔值来检查是否已点击刷新以取消缩略图加载器。有什么想法吗?

public class LoadItems extends AsyncTask<Void, Void, Boolean> {

private Activity activity;
private static boolean loading = false;
public static final AtomicBoolean refreshing = new AtomicBoolean(false);
private static final String TAG = "LoadItems";
private int start;

private List<ListItem> items;

public LoadItems(Activity activity) {
    this.activity = activity;
}

@Override
protected void onPreExecute() {
    loading = true;
    start = ItemViewer.itemList.size();
}

@Override
protected Boolean doInBackground(Void... arg0) {

    items = WebFunctions.getMoreItems(activity);
    return (items != null);
}


protected void onPostExecute(Boolean success) {
    if (success) {
        for (ListItem item: items) {
            ItemViewer.itemList.add(item);
            Log.d(TAG, "added item " + item.getTitle());
        }
        LoadThumbnails thumbnailLoader = new LoadThumbnails();
        thumbnailLoader.execute(start, ItemViewer.itemList.size());
    }
    loading = false;
}

public void protectedExecute() {
    if (!loading)
        execute();
}

public void refresh() {
    if (!refreshing.getAndSet(true)) {
        WebFunctions.reset();
        ItemViewer.itemList.removeAllItems();
        execute();
    }
}

}



public class LoadThumbnails extends AsyncTask<Integer, Void, Drawable> {
private int position;
private int end;

@Override
protected Drawable doInBackground(Integer... params) {
    position = params[0];
    end = params[1];
    Drawable thumbnail = null;
    synchronized(ItemViewer.itemList) {
        if (LoadItems.refreshing.get())
            cancel(true);
        String url = ItemViewer.itemList.get(position).getThumbnailUrl();
        if (!url.isEmpty())
            thumbnail = WebFunctions.loadDrawableFromUrl(ItemViewer.activity, url);
    }
    return thumbnail;
}

protected void onPostExecute(Drawable d) {

    synchronized (ItemViewer.itemList) {
        if (LoadItems.refreshing.get())
            cancel(true);
        if (d != null)
            ItemViewer.itemList.setThumbnail(position, d);
        position++;
        if (position < end) {
            LoadThumbnails lt = new LoadThumbnails();
            lt.execute(position, end);
        }
    }
}

}

【问题讨论】:

    标签: android synchronization android-listview android-asynctask


    【解决方案1】:

    这很容易解决。每当用户点击刷新按钮时,请确保在创建新任务之前对您创建的最后一个异步任务调用 cancel()。例如,

    private void onRefreshClick(View v) {
      if(mLastLoadItemTask != null) mLastLoadItemTask.cancel(true);
      if(mLastLoadThumbnailTask != null) mLastLoadThumbnailTask.cancel(true);
      mLastLoadItemTask = new LoadItems(...);
      mLastLoadItemTask.execute();
    }
    

    然后,在每个异步任务的onPostExecute 中,首先通过调用isCancelled() 检查它们是否被取消。如果它们被取消,请确保 onPostExecute 方法仅返回不起作用。例如,

      protected void onPostExecute(...) {   
             if(isCancelled()) return;
             //Adding items to list 
             //Or start load thumbnail task  
         }
    

    如您所见,这应该可以防止任何无意或过时的更新,因为 onPostExecute 方法和您的 cancel 调用都将在主线程上发生。我建议的最后一件事是更改您的 loadThumbs 任务,以便能够通过检查 isCancelled() 来尽快停止工作,只要这样做是有意义的。

    【讨论】:

      【解决方案2】:

      以下步骤可能会有所帮助:

      1. 缓存结果,您之前从网上提取的任何内容都应保存并在应用程序启动时快速恢复。这样可以避免应用程序启动时出现长时间延迟和空白屏幕,进而阻止用户按下“重新加载”

      2. 创建一个布尔变量reload_in_progress,当你开始从网上提取数据时将其设置为true,并在所有缩略图准备好时将其设置为false。当reload_in_progresstrue 时,“重新加载”点击处理程序应忽略点击。

      3. 向用户显示progress bar 的一些国王,所以他知道它已经重新加载并且不会再次推送reload

      4. 几乎忘记了,永远不要更新“实时”显示给用户的数据,这会导致美妙的情况,当用户单击项目时,它正在改变并执行与他预期完全不同的事情。长时间更新应保留其数据,并仅在一切准备就绪时快速将旧数据交换为新数据。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-04-25
        • 1970-01-01
        • 2015-08-19
        • 2014-04-09
        • 2011-02-11
        • 1970-01-01
        • 2021-10-21
        • 1970-01-01
        相关资源
        最近更新 更多