2015-01-16 102 views
0

我有一個AsyncTask刷新我的listView onPostExecute事件,並檢索doInBackground事件中的一些數據。問題是我的AsyncTask在onScroll事件中被多次執行。我怎樣才能防止它做到這一點?順便說一下,我試圖在我的應用程序中創建一個Inifinite Scroll。也許我做錯了什麼? 這裏是我的onScroll事件:如何防止AsyncTask在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

+0

條件是什麼防範? –

+0

AsyncTask平均執行10次,直到用戶的手指離開屏幕。 – Rishka

+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

+0

什麼是currentPage和startingPageIndex變量?以及totalItemCount如何小於previousTotalItemCount? – Rishka

+0

@Rishka對不起,我應該留下評論。在你的實現中不使用currentPage和startingPageIndex。我刪除了它們 – andrei

+0

非常感謝你,@schopy,感謝你的鏈接,我設法使它工作和完美工作=)我不得不重做我的所有代碼,但它是值得的)) – Rishka

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(); 
    } 
} 

基本上,只要跳過創建一個新的異步任務,如果如果運行或掛起狀態運行它。應該管用。

+0

我已經triend爲了實現狀態檢查,但是一旦AsyncTask被執行,它就永遠不會成爲某些reasos的「FINISHED」狀態(( – Rishka

+0

這很奇怪,在這種情況下,只需要顛倒所有的條件語句,檢查狀態PENDING和RUNNING,如果不是這樣,請創建一個新的 –

+0

檢查編輯的代碼是否有效@Rishka –

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(); 
} 
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(); 
    } 
}