2012-04-19 48 views
0

我有一個定時器運行,然後熄滅,並做了一些事情,定時器啓動罰款。Android定時器崩潰取消

然後我想要做的是點擊一個按鈕,然後創建一個電子郵件。除了在計時器運行時單擊該按鈕之外,一切正常,應用程序崩潰。當按下按鈕時試圖取消計時器時,也會使應用程序崩潰。

任何幫助,將不勝感激。

下面的代碼片段:

public class myApplication extends Activity { 
    StringBuilder str; 
    Timer t; 
    Button mailbutton; 

    public void onCreate(Bundle savedInstanceState) { 

     final StringBuilder str = new StringBuilder(1000); 
     super.onCreate(savedInstanceState); 


     setContentView(R.layout.main); 

     addListenerOnButton(); 


     TimerTask task = new TimerTask() { 

      @Override 
      public void run() 
      { 
      /// do stuff here 
      } 
     } 

     t = new Timer(); 
     t.schedule(task,2000,2000); 

    } 


    public void addListenerOnButton() { 

     mailbutton = (Button) findViewById(R.id.emailbutton); 

     mailbutton.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View arg0) { 

       t.cancel(); 

       Intent i = new Intent(Intent.ACTION_SEND); 
       i.setType("text/plain"); 
       i.putExtra(Intent.EXTRA_EMAIL , new String[]{"[email protected]"}); 
       i.putExtra(Intent.EXTRA_SUBJECT, "subject"); 
       i.putExtra(Intent.EXTRA_TEXT , str.toString()); 
       try { 
        startActivity(Intent.createChooser(i, "Send mail")); 
       } catch (android.content.ActivityNotFoundException ex) { 
       } 
      } 
     }); 
    } 
} 

logcat的輸出:

04-19 09:13:11.143: W/dalvikvm(12613): threadid=1: thread exiting with uncaught exception (group=0x40c421f8) 
04-19 09:13:11.148: E/AndroidRuntime(12613): FATAL EXCEPTION: main 
04-19 09:13:11.148: E/AndroidRuntime(12613): java.lang.NullPointerException 
04-19 09:13:11.148: E/AndroidRuntime(12613): at uk.co.application.applicationActivity$2.onClick(applicationActivity.java:94) 
04-19 09:13:11.148: E/AndroidRuntime(12613): at android.view.View.performClick(View.java:3591) 
04-19 09:13:11.148: E/AndroidRuntime(12613): at android.view.View$PerformClick.run(View.java:14263) 
04-19 09:13:11.148: E/AndroidRuntime(12613): at android.os.Handler.handleCallback(Handler.java:605) 
04-19 09:13:11.148: E/AndroidRuntime(12613): at android.os.Handler.dispatchMessage(Handler.java:92) 
04-19 09:13:11.148: E/AndroidRuntime(12613): at android.os.Looper.loop(Looper.java:137) 
04-19 09:13:11.148: E/AndroidRuntime(12613): at android.app.ActivityThread.main(ActivityThread.java:4507) 
04-19 09:13:11.148: E/AndroidRuntime(12613): at java.lang.reflect.Method.invokeNative(Native Method) 
04-19 09:13:11.148: E/AndroidRuntime(12613): at java.lang.reflect.Method.invoke(Method.java:511) 
04-19 09:13:11.148: E/AndroidRuntime(12613): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790) 
04-19 09:13:11.148: E/AndroidRuntime(12613): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557) 
04-19 09:13:11.148: E/AndroidRuntime(12613): at dalvik.system.NativeStart.main(Native Method) 
+0

從logcat中添加你的錯誤日誌。 – blessenm 2012-04-19 00:08:43

+0

你可以發佈崩潰日誌嗎? – 2012-04-19 00:08:52

+0

請發佈locat stacktrace – slayton 2012-04-19 00:09:02

回答

2

這個計時器的目的究竟是什麼?我無法想象你會如何使用它,並不斷重複每2秒運行一次。你可能會碰到的一件事是Android的線程問題。該計時器任務在與Android UI使用的主線程不同的線程上運行。如果您正在觸摸android widgets或其他實例變量,那麼您最終會遇到線程安全問題,如果您嘗試這樣做,Android經常會拋出異常。所以這歸結於你正在試圖用這個線程來完成什麼比創建像這樣的另一個線程更好的工作。通常我們會使用Handler在主線程上定期運行任務,而不是像這樣使用Timer,因爲它引入了線程問題。

更新:

你只是證實了你剛纔描述了一個嚴重的線程安全問題。我所說的線程安全意味着你可能有兩個線程同時讀/寫同一個內存位置。這是一個大問題。事實上,通過您自己的承認,您的StringBuilder實例在計時器線程和按鈕回調之間共享,這意味着您通過閱讀該StringBuilder肯定會遇到線程安全問題。

你將會遇到不斷的不可預測的問題,而且當用戶操作時,你的代碼永遠不會穩定。首先,沒有理由從另一個線程讀取GPS,因爲LocationManager會隨着它的變化而定期給你打電話。只需簡單地將它追加到StringBuilder或ArrayList中即可。 GPS回調在主線程上運行,因此讀取該變量的按鈕邏輯不可能在修改該變量的同時發生。

您需要從代碼中刪除該計時器,並使用主線程完成所有工作。或者你必須同步訪問你的數據結構。 Android中發生的大部分回調都在主線程中運行。所以,如果你只是將記錄歷史值的邏輯移到那裏的數據結構中,而不是在你的計時器中,你會沒事的。您可能需要單獨記錄GPS,然後將其格式化爲按鈕點擊處理程序中的字符串。

您的NPE位於文件的第94行。不知道行號碼來源代碼,我們無法幫助你。但是,這些是您遇到線程安全問題時遇到的問題類型。而且他們會讓你發瘋,所以有必要發表我的警告,並且瞭解更多關於線程安全和控制的信息。

+0

定時器基本上讀取一組不斷變化的變量(它們包含來自GPS的位置信息之類的東西),計時器每隔幾秒就會獲取這些變量的值並將其附加到StringBuilder。 StringBuilder是直到你想要點擊按鈕並取消定時器,然後使用StringBuilder中的String來構建的。 – fdf33 2012-04-19 08:21:33

+0

更新了我有關您使用此計時器任務創建的嚴重線程問題的答案。 – chubbsondubs 2012-04-19 12:45:04

+0

謝謝。採取了你的建議,並採用線程安全的方式。 – fdf33 2012-04-21 16:39:24

0
mailbutton = (Button) findViewById(R.id.emailbutton); 

     mailbutton.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View arg0) { 

       t.cancel(); 

       Intent i = new Intent(Intent.ACTION_SEND); 
       i.setType("text/plain"); 
       i.putExtra(Intent.EXTRA_EMAIL , new String[]{"[email protected]"}); 
       i.putExtra(Intent.EXTRA_SUBJECT, "subject"); 
       i.putExtra(Intent.EXTRA_TEXT , str.toString()); 
       try { 
        startActivity(Intent.createChooser(i, "Send mail")); 
       } catch (android.content.ActivityNotFoundException ex) { 
       } 
      } 
     }); 

上述行必須在OnCreate中(),因爲你有一個觀點(R.layout.main)設置oncreate和你的函數addListenerOnButton()不知道主佈局。

+0

謝謝,我改變了這一點,但仍然得到了崩潰。已經更新了上面的LogCat輸出。 – fdf33 2012-04-19 08:19:04