2012-02-14 60 views
0

編輯:已解決。對不起,我發現,雖然我的數據加載發生在後臺線程中,但解析數據的回調不是。數據的解析需要很長時間,這就是鎖定我的線程。ASynchTask睡在doinbackground鎖定UI線程

編輯:它已經引起我的注意,我的首要問題(ProgressDialog不再旋轉)可能是由我使用ProgressDialog而不是UI線程被阻止的問題引起的。如果是這樣的話,我該如何解決這個問題?

編輯:澄清,這並沒有永遠鎖定整個程序。一旦加載了所有內容,進度對話框將被解除,並且新的活動將被啓動。我的問題是,雖然它加載,整個UI鎖起來(即progressdialog停止旋轉)

TL; DR:Thread.sleep()方法在doInBackground()被鎖定在UI線程

我有一個應用程序,當某個特定活動打開時,開始從我的後端加載後臺的大量數據,例如與計劃相關的大量數據。這些信息不會馬上使用,但可以在用戶嘗試訪問它時使用(即通過點擊計劃按鈕並啓動計劃活動)。

如果用戶在點擊計劃按鈕之前等待了一下,所有數據加載,計劃活動打開,並顯示一切都很好。我的問題是如果他們在數據加載之前點擊按鈕。

我在這裏的解決方案是創建一個ASyncTask,它顯示ProgressDialog,同時定期檢查數據是否已完成加載,否則將進入休眠狀態。它知道數據是通過一些應用程序範圍的布爾變量完成加載的。我的問題是,即使Thread.sleep()在doinbackground()中運行,它仍然鎖定UI線程。

我使用的是自定義的AsyncTask,定義如下:

public class LoadWithProgressDialog extends AsyncTask<Void, Void, Boolean>{ 
    private ProgressDialog pd; //the progress dialog 
    private String title; //the title of the progress dialog 
    private String message; //the body of the progress dialog 
    private Runnable task; //contains the code we want to run in the background 
    private Runnable postTask; //execute when the task ends 
    private Context c; 


    public LoadWithProgressDialog(Context context,String t, String m,Runnable r, Runnable postR){ 
     super(); 
     c = context; 
     task = r; 
     postTask = postR; 
     title = t; 
     message = m; 
    } 

    @Override 
    protected void onPreExecute(){ 
     pd = ProgressDialog.show(c,title, message, false, false); 
    } 

    @Override 
    protected Boolean doInBackground(Void... params) { 
     task.run(); 
     return true; 
    } 


    @Override 
    protected void onPostExecute(Boolean result) { 
     pd.dismiss(); 
     if(postTask != null) 
      postTask.run(); 
    } 

和經由(例如)調用它:

if(loadingSchedule){ 

      LoadWithProgressDialog lwpd = new LoadWithProgressDialog(thisClass,"Loading","Loading Schedule", new Runnable() { 
       public void run(){ 
        while(loadingSchedule){ 
          try { 
           Thread.sleep(1000); 
          } catch (InterruptedException e) { 
           e.printStackTrace(); 
          } 

        } 
       } 
      },new Runnable() { 
       public void run(){ 

        Intent i= new Intent(thisClass, Schedule.class); 
        i.putExtra("numberIneed",index); 
        startActivity(i); 
       } 
      }); 
      lwpd.execute(); 

(I縮短到訪問全局變量設置爲 「loadingSchedule」使其更容易閱讀)

如何使這不鎖定UI線程?

回答

0

您的代碼看起來正確,並且不應阻止主線程。

所以使用調試器!將斷點放入doInBackground,Thread.sleep,onPostExecute,lwpd.execute之後,您將瞭解代碼的獲取位置和時間。

嘗試找到「UI線程被阻塞的位置」的答案。

+0

對不起,請參閱我的編輯澄清。一旦完成後臺加載,所有事情都會再次運行。它只是鎖定了持續時間(ProgressDialog不旋轉)。我不知道如何識別UI鎖定的時間,因爲除了應該保持progressdialog旋轉(我沒有寫入)之外,沒有任何代碼在運行。 – 2012-02-15 00:19:11

5

Thread.sleep()方法在doInBackground()被鎖定在UI線程

Thread.sleep()方法在doInBackground()不鎖UI線程,就像它的名字所說,任務在後臺做異步。

你的UI線程沒有被鎖定。它實際上是在AsyncTask啓動之前(在onExecute()方法中)彈出的ProgressDialog,並在AsyncTask執行期間(在doInBackground()方法中)繼續顯示並阻止用戶與基礎活動的交互。並在AsyncTask完成後終於解散。 (在onPostExecute()方法)

我有一個應用程序是,特定活動打開時,開始加載大量的數據在從我的後端

背景這是一種常見用例時,創建一個在後臺加載數據的AsyncTask實現會更有效率,而不是創建一個顯示ProgressDialog的ASyncTask,同時定期檢查數據是否已完成加載,否則將進入休眠狀態。

查看API here,它包含了如何正確使用它的好例子。

+0

1)我知道ProgressDialog彈出並阻止用戶與基礎活動的交互。我的問題是PD不旋轉。我意識到這可能表示或不表示UI線程被阻止。 2)我在後臺加載數據。這個progressdialog是如果他們在數據準備好之前試圖訪問數據的,所以我需要用戶等待,直到完成加載。 – 2012-02-15 00:45:35

+0

對於旋轉問題,看看[this](http://stackoverflow.com/questions/3119676/android-progress-dialog-spinner-not-spinning)有幫助嗎? – yorkw 2012-02-15 01:45:00

+0

@yorkw我有這個問題的對話框阻塞用戶界面,所以如何處理它?!如你所知,它必須首先在主線程中運行 – 2016-01-14 13:25:36