2011-05-09 75 views
0

嘿, 因此,環顧四周看來,共識是通過使用publishProgress()將更新用戶界面以進行更長時間的計算。我似乎不喜歡實現這個,但是,因爲當我運行這個代碼時,我得到了一個ANR。你能幫我理解爲什麼嗎?在AsyncTask中更新用戶界面

這裏是我的代碼: http://pastebin.com/zQNhkDJ9

http://pastebin.com/HcNZtAsx

+0

我沒有看到您的代碼中您創建和執行AsyncTask的任何位置。這是否發生在另一個文件? – BigFwoosh 2011-05-09 18:40:24

+0

是的,我不認爲我需要發佈該 – Cody 2011-05-09 18:41:51

回答

1

你的問題可能是你的doInBackground功能只是打電話publishProgress。您的所有工作都在publishProgress中完成,它在UI線程上運行,所以您仍然可以通過這種方式獲得ANR。您需要在doInBackground中完成繁重的工作,然後一旦完成處理,您可以更新UI線程。

+0

計算在我的用戶界面中應該是什麼顏色的視圖是我的繁重工作。那麼如何避免使用戶界面崩潰呢? – Cody 2011-05-09 18:51:32

+0

沒錯,但是你正在計算你的onProgressUpdate函數的內部。它需要在doInBackground內完成,然後您應該使用onProgressUpdate中的新值更新顏色。 – BigFwoosh 2011-05-09 18:52:39

0

你需要讓你的AsyncTask成爲一個靜態的內部類,它有一個屬性,它是對你的Activity的引用。然後你可以直接調用Activity上的方法 - 就像UIupdate()一樣。

您必須注意的一個問題是,您現在必須非常小心地清除對onPause回調中的Activity的引用,否則您設置了循環引用,這會導致內存泄漏。

我的模式是有另一個基本的Java對象,通常是另一個私人靜態類,我稱之爲「StateHolder」,它是我的網關,用於處理AsyncTask的東西,比如初始化它並清除它(設置爲NULL )並在輪換更改期間取消正在進行的任何任務。在「onRetainNonConfigurationInstance」回調中,您可以使用StateHolder作爲編組對象。

下面是一些粗糙的代碼:

私有靜態類GetConnectionsStatusTask擴展的AsyncTask { 私人BoothActivity mActivity; 私人異常mReason;

public GetConnectionsStatusTask(BoothActivity activity) { 
    super(); 
    mActivity = activity; 
} 

public void setActivity(BoothActivity activity) { 
    mActivity = activity; 
} 

@Override 
protected void onPreExecute() { 
    if(mActivity != null) { 
     mActivity.startProgressBar("Loading", "Please wait"); 
    } 
} 

@Override 
protected Connections doInBackground(Void... values) { 
    try { 
     App app = (App)mActivity.getApplication(); 
     return(app.getApp().userConnections()); 
    }catch(Exception e) { 
     mReason = e; 
     return(null); 
    } 
} 

@Override 
protected void onPostExecute(Connections status) { 
    super.onPostExecute(status); 
    if(mActivity != null) { 
     mActivity.completedConnectionsStatusCheck(status, mReason); 
    } 
}  
} 

私有靜態類的StateHolder { 私人GetConnectionsStatusTask connectionsTask;

public void cancelTasks() { 
     if (connectionsTask != null) { 
      connectionsTask.setActivity(null); 
      connectionsTask.cancel(true); 
      connectionsTask = null; 
     } 
} 
    public void setActivityForTasks(BoothActivity activity) { 
     if (connectionsTask != null) { 
      connectionsTask.setActivity(activity); 
     } 
} 

    public void startConnections(BoothActivity activity) { 
     if(mIsConnectionsChecking == false) { 
      mIsConnectionsChecking = true; 
      connectionsTask = new GetConnectionsStatusTask(activity); 
      connectionsTask.execute();    
     } 
    } 
    } 
中的onPause

然後,我有這樣的代碼:

 if(mStateHolder != null) { 
      mStateHolder.cancelTasks(); 
     } 

而在的onCreate你可以重新虛增您的StateHolder像這樣:

Object retained = getLastNonConfigurationInstance(); 
    if(retained != null && retained instanceof StateHolder) { 
     mStateHolder = (StateHolder) retained; 
     mStateHolder.setActivityForTasks(this); 
    } else { 
     mStateHolder = new StateHolder(); 
    } 

這也將重新初始化您的StateHolder與當前的活動,所以你可以重新建立任何UI小部件,如進度條更新等。

使用此模式,您實際上可以運行異步任務,並通過進度條重新初始化自己來處理輪換更改。