2014-01-14 20 views
-1

我不太清楚如何調試我目前在Android應用程序中看到的現象。 我有一個活動,只是做一些網絡的東西(這需要在後臺完成)。 此活動使用Intent從PreferencesFragment啓動。 當用戶選擇首選項時,Intent被觸發並且Activity被啓動(然後它執行網絡連接並使用finish()退出)。onCreate有時在後臺運行

我創建了一個AsyncTask來在後臺執行網絡操作。 (我以爲onCreate很可能會在UI線程中運行......) 但是接着發生異常: java.lang.RuntimeException:無法在未調用Looper.prepare()的線程中創建處理程序

onCreate()已經在後臺運行了嗎?

爲了測試,我將網絡功能直接轉移到了onCreate()。 這是工作得很好... ...至少幾次。

突然拋出了一個異常: 了java.lang.RuntimeException:無法啓動活動ComponentInfo {...}:android.os.NetworkOnMainThreadException

移動代碼發回的AsyncTask幫助...的一段時間。

有誰知道爲什麼會出現這種現象? 當onCreate()在UI線程中運行時,以及在onCreate()在後臺運行時是否有其他情況?

我的類是如此簡單:

public class ReregisterInDb extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     new ReregisterAsyncTask().execute(""); // solution 1 

      // solution 2 
     //GCMFunctions gcmFunctions = new GCMFunctions(getApplicationContext()); 
     //gcmFunctions.registerInDb(); 

     super.onCreate(savedInstanceState); 
     finish(); 
    } 

    class ReregisterAsyncTask extends AsyncTask<String, Void, Void> { 

     @Override 
     protected Void doInBackground(String... params) { 
      GCMFunctions gcmFunctions = new GCMFunctions(getApplicationContext()); 
      gcmFunctions.registerInDb(); 
      return null; 
     } 

    } 

} 
+0

爲什麼你甚至爲此開始一項活動?在我看來,你可以將異步任務聲明爲一個單獨的類,並使用它......不管怎樣,你不應該僅僅爲了做後臺工作而使用一個活動 - 要麼從你當前的活動中啓動一個AsyncTask,要麼使用一項服務。 – npace

+0

我想避免使用僅用於此目的的服務。編程開銷似乎太多了。我知道當前的實現不是很聰明......但是如何從PreferencesFragment啓動一個AsyncTask?我可以啓動Intents,然後啓動活動。也許有更好的解決方案...? – TomS

回答

0

我終於找到了這種奇怪的行爲的原因。 我沒有發佈registerInDb()方法的內容。 在該方法中,有一個吐司:

Toast.makeText(context, 
    "Not currently registered with GCM. [...]", 
    Toast.LENGTH_LONG).show(); 

此消息導致了異常......

解決的辦法是:

  • 調用在UI線程的功能,從而使吐司消息的工作和 輸入代碼heremove AsyncTask只覆蓋實際的網絡代碼。

對不起,沒有提供所有的細節。我不認爲Toast消息是根本原因。

我瞭解到您不能在AsyncTasks中擁有Toasts。總是必須在UI線程上運行。

0

調用super.onCreate(...)把那個正確的開始,因爲我如下所示之前,您不能做任何事情。編輯:此外,您在AsyncTask中使用getApplicationContext可能會導致問題,請嘗試創建全局上下文變量並在onCreate中初始化該變量,然後查看是否有效。

Context mContext; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    mContext = this; 
    new ReregisterAsyncTask().execute(""); // solution 1 

    finish(); 
} 

class ReregisterAsyncTask extends AsyncTask<String, Void, Void> { 

    @Override 
    protected Void doInBackground(String... params) { 
     GCMFunctions gcmFunctions = new GCMFunctions(mContext); 
     gcmFunctions.registerInDb(); 
     return null; 
    } 

} 
+0

感謝您的提示。我相應地更改了代碼,但經過一些嘗試後,我仍然得到一個異常拋出(java.lang.RuntimeException:無法在未調用Looper.prepare()的線程中創建處理程序)。所以,片狀行爲依然存在。 – TomS

+1

@TomS我剛剛注意到你在AsyncTask中使用'getApplicationContext'。這是一個壞主意,我相當肯定它是你問題的根源。參考我上面的編輯。 – anthonycr

0

嘗試移動性的方法完成()的調用在異步任務的方法onPostExecute

+0

然後將調用活動「完成()」編輯?或者我如何指定我想完成()調用者? – TomS

+0

我仍然看到相同的行爲。 – TomS