簡體   English   中英

Android計時器崩潰取消

[英]Android Timers Crashing On Cancel

我有一個計時器運行,然后關閉並做一些事情,計時器啟動正常。

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

任何幫助,將不勝感激。

這是代碼片段:

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@domain.com"});
                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)

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

更新:

您剛剛在剛才描述的內容中確認了嚴重的線程安全問題。 線程安全的意思是你有兩個線程可以同時讀/寫同一個內存位置。 這是一個大問題。 事實上,你自己承認,你的StringBuilder實例是在定時器線程和按鈕回調之間共享的,這意味着你在讀取StringBuilder時肯定會遇到線程安全問題。

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

您需要從代碼中刪除該計時器,並使用主線程完成所有工作。 或者您必須同步對數據結構的訪問。 Android中發生的大多數回調都在主線程上運行。 因此,如果您只是將記錄歷史值的邏輯移動到那里的數據結構中,而不是在計時器中,那么你會沒事的。 您可能必須單獨記錄您嘗試記錄的其他任何內容,但您可以在按鈕單擊處理程序中將它們格式化為您的字符串。

您的NPE位於文件的第94行。 如果不知道源代碼的行號,我們無法幫助您。 但這些是您遇到線程安全問題時遇到的問題類型。 它們會讓你發瘋,因此有必要發出警告,並更多地了解線程並安全地控制它。

   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@domain.com"});
                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()中,因為你在oncreate中設置了一個視圖(R.layout.main),你的函數addListenerOnButton()不知道主要的布局。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM