2011-04-30 53 views
1

那麼,請不要問我爲什麼,但我需要啓動一個同步和阻塞活動,以便程序流程在其完成之前不會繼續。我知道如何做一個同步對話框,但我怎麼做一個同步活動?如何進行阻止和同步活動?

以下是兩種方法我試過,但失敗:

// In the 1st activity, start the 2nd activity in the usual way 
startActivity(intent); 
Looper.loop();  // but pause the program here 
// Program continuse running afer Looper.loop() returns 
.... 

// Then, in the second activity's onBackPressed method: 
public void onBackPressed() { 
    // I was hoping the following quit() will terminate the loop() call in 
    // the first activity. But it caused an exception "Main thread not allowed 
    // to quit." Understandable. 
    new Hanlder().getLooper().quit(); 
} 

我還試圖用另一個線程來實現這一目標:

// In the first activity, start a thread 
SecondThread m2ndThread = new SecondThread(this); 
Thread th = new Thread(m2ndThread, "Second Thread"); 
th.run(); 
synchronized(m2ndThread) { 
    m2ndThread.wait(); 
} 

class SecondThread implements Runnable { 

    Activity m1stActivity; 

    SecondThread(Activity a) { 
     m1stActivity = a; 
    } 

    public void run() { 
     Looper.prepare(); 
     Handler h = new Handler() { 
      public void handleMessage() { 
       Intent intent = new Intent(m1stActivity, SecondActivity.class); 
       m1stActivity.startActivity(intent); // !!!!!!!!!!!!!! 
      } 
     } 
     h.sendEmptyMessage(10); // let it run 
     Looper.quit(); 
    } 
} 

然而,這種方法是行不通的,因爲當我m使用第一個活動來啓動第二個活動,主線程已處於等待狀態並且什麼都不做。所以第二項活動甚至沒有創建。 (這很具有諷刺意味:你必須使用一項活動來開始一項活動,但是當它已經處於等待狀態時你怎麼能這樣做?)

+1

你不能只顯示一個ProgressDialog?這將阻止用戶在執行您正在執行的任何任務時能夠與您的活動進行交互。 – dmon 2011-04-30 18:14:47

+0

@dmon,嗯......,是ProgressDialog阻止?嗯...有趣。我肯定會試一試。非常感謝。 – wwyt 2011-04-30 18:40:53

+0

我的意思是它不會阻止主線程執行,顯然,但你可以在後臺執行你的工作,而用戶留在那裏盯着真棒棘手thinghy。 – dmon 2011-04-30 18:42:55

回答

8

你不能。

這就是它的全部。你不能這樣做。活動在主線程上始終執行。您的主線程必須主動運行其事件循環。它總是被打破,以阻止主線程的事件循環。總是。

+0

一個很好的答案,給了我更多的Android的見解。非常感謝! – wwyt 2011-04-30 18:38:15

1

所有活動都是異步的。但是,如果要在活動完成之前阻止其他應用程序流,則可以在活動設置的標誌上插入依賴項。最封閉的方式是隨意攜帶意圖/活動/回報流。你可以:

聲明國旗在該對象的全局範圍:

boolean syncBlock = false; 
int ASYNC_ACTIVITY_REQUEST_CODE = 1; // Arbitrary unique int 

在對象的範圍要啓動的新活動包括:

Intent asyncIntent = new Intent(this, AsyncActivity.class); 
syncBlock = true; 
startActivityForResult(asyncIntent, ASYNC_ACTIVITY_REQUEST_CODE); 
while(syncBlock) {} 

,並在啓動該活動對象:

onActivityResult(int requestCode, int resultCode, Intent data) 
{ 
    switch(requestCode) 
    { 
    case ASYNC_ACTIVITY_REQUEST_CODE: 
    { 
     syncBlock = false; 
     break; 
    } 

[...] 
} 

這是一個黑客原油,如果你在你的UI線程阻塞(如。在您的MAIN活動中),您會阻止所有內容,包括您的用戶可能期望回覆但不會的其他UI功能。這是一個很大的nono,你應該學會使用使Android應用程序工作的異步流程。但如果你絕對必須...

+0

雖然這很粗糙,但確實有效!我可以建議,儘管這不是使用緊密循環(while循環會執行很多次),而是你看[CountDownLatch](http://developer.android.com/reference/java/util/concurrent/CountDownLatch.html )並在調用startActivityForResult之後調用latch上的await(),並在onActivityResult中調用countDown()? – 2015-11-11 19:54:36

+1

@BK:當然,同步鎖上的while循環性能很差,並不完全安全。事實上,正如我所提到的在UI線程中阻塞是一個壞主意。實現CountDownLatch更好。但是如果你的發佈時間長度超過了我發佈的原始屏蔽時間,那麼你應該多走一步,在設計中擁抱異步,而不是加倍阻止粗糙的屏蔽。 – Matthew 2015-11-13 00:19:34

+0

你是多麼正確!我很快指出了一個優化,但你說的正確的做法是採用異步方式。好決定! – 2015-11-14 07:14:45