如何防止在onScroll事件中多次执行AsyncTask?

时间:2015-01-16 13:53:19

标签: android android-asynctask infinite-scroll

我有一个AsyncTask,它在onPostExecute事件中刷新我的listView,并在doInBackground事件中检索一些数据。问题是我的AsyncTask在onScroll事件中被多次执行。我怎么能阻止它呢? 顺便说一句,我正在尝试在我的应用程序中创建一个Inifinite Scroll。也许我做错了什么? 这是我的onScroll活动:

@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
    previousTotal = totalItemCount;
    try {
        itemNews = listAdapter.getData();
    }catch (Exception e){
        System.out.println("itemNews is empty");
    }
    if(totalItemCount > 2) {
        artId = itemNews.get(firstVisibleItem).articleId;
    }
    if(firstVisibleItem > ((previousTotal)/2))
    {
        UpdateListAsyncTask updateListAsyncTask = new UpdateListAsyncTask(artId, mActivity, listAdapter);
        updateListAsyncTask.execute();
    }

这是我的AsyncTask:

public class UpdateListAsyncTask extends AsyncTask<Void, Void, Void> {
    public int currentArticleId;
    public Activity mActivity;
    RemoteData remoteData;
    public ListAdapterRegular listAdapter;
    UpdateListAsyncTask(int currentArticleId, Activity activity, ListAdapterRegular listAdapterRegular)
    {
        this.mActivity = activity;
        this.currentArticleId = currentArticleId;
        this.listAdapter = listAdapterRegular;
    }
    @Override
    protected void onPreExecute()
    {
        remoteData = new RemoteData(mActivity, "News");
    }
    @Override
    protected Void doInBackground(Void... params) {
        try{
            remoteData.writeServerData("&from=" + currentArticleId);
            System.out.println("DoInBackground writeServerData");
        }catch (Exception e)
        {
            e.printStackTrace();
            System.out.println("UpdateListAsyncTask: doInBackground exception!");
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void result)
    {
        List<News> dataList = Select.from(News.class).orderBy("date DESC").list();
        System.out.println("onPostExecuteInitiated");
        listAdapter.clear();
        listAdapter.addAll(dataList);
        listAdapter.notifyDataSetChanged();
    }
}

非常感谢任何帮助和想法! 更新: 我不得不重做我的代码,但它值得。我已根据链接https://github.com/codepath/android_guides/wiki/Endless-Scrolling-with-AdapterViews

完成了

4 个答案:

答案 0 :(得分:1)

我会用这样的东西

// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
    previousTotal = totalItemCount;
    try {
        itemNews = listAdapter.getData();
    }catch (Exception e){
        System.out.println("itemNews is empty");
    }

    // If the total item count is zero and the previous isn't, assume the
    // list is invalidated and should be reset back to initial state
    if (totalItemCount < previousTotalItemCount) {
        this.previousTotalItemCount = totalItemCount;
        if (totalItemCount == 0) { this.loading = true; } 
    }

    if(totalItemCount > 2) {
        artId = itemNews.get(firstVisibleItem).articleId;
    }

    // If it’s still loading, we check to see if the dataset count has
    // changed, if so we conclude it has finished loading and update the current page
    // number and total item count.
    if(loading && totalItemCount > previousTotalItemCount) {
        loading = false;
        previousTotalItemCount = totalItemCount;
    }

    if(!loading && firstVisibleItem > ((previousTotal)/2))
    {
        loading = true;
        UpdateListAsyncTask updateListAsyncTask = new UpdateListAsyncTask(artId, mActivity, listAdapter);
        updateListAsyncTask.execute();
    }
}

PS当我实现无限滚动时,我以此为例https://github.com/codepath/android_guides/wiki/Endless-Scrolling-with-AdapterViews

答案 1 :(得分:1)

您的方法可以有其他改进,但如果没有任何改进,如果您想要的是多个异步任务无法运行,为什么不试试呢?

更改

if(firstVisibleItem > ((previousTotal)/2))
{
    UpdateListAsyncTask updateListAsyncTask = new UpdateListAsyncTask(artId, mActivity, listAdapter);
    updateListAsyncTask.execute();
}

if(firstVisibleItem > ((previousTotal)/2))
{
    if(mUpdateListAsyncTask != null && (mUpdateListAsyncTask.getStatus == AsyncTask.Status.RUNNING|| mUpdateListAsyncTask.getStatus ==AsyncTask.Status.PENDING)) {
         return;
     } else {
         mUpdateListAsyncTask = new UpdateListAsyncTask(artId, mActivity, listAdapter);
         updateListAsyncTask.execute();
     }
 }

基本上,只需跳过创建新的异步任务并在状态为RUNNING或PENDING时运行它。应该工作。

答案 2 :(得分:0)

您可能希望执行上一个任务,因此我会将UpdateListAsyncTask updateListAsyncTask作为属性。

现在改变这个:

if(firstVisibleItem > ((previousTotal)/2))
{
    UpdateListAsyncTask updateListAsyncTask = new UpdateListAsyncTask(artId, mActivity, listAdapter);
    updateListAsyncTask.execute();
}

到此:

if(firstVisibleItem > ((previousTotal)/2))
{
    try{
        updateListAsyncTask.cancel(true);
    }catch(Exception ex){}

    updateListAsyncTask = new     UpdateListAsyncTask(artId, mActivity, listAdapter);
    updateListAsyncTask.execute();
}

答案 3 :(得分:0)

private UpdateListAsyncTask updateListAsyncTask = null;

...
if(firstVisibleItem > ((previousTotal)/2))
    {
//Create just if not exist or if it's finished
    if (updateListAsyncTask == null || updateListAsyncTask.getStatus() == Status.FINISHED) {
        updateListAsyncTask = new UpdateListAsyncTask(artId, mActivity, listAdapter);
    }

//Start only if it's not already running
    if (updateListAsyncTask.getStatus() == Status.PENDING) {
        updateListAsyncTask.execute();
    }
}