Android计时器崩溃取消

时间:2012-04-19 00:04:16

标签: java 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@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 个答案:

答案 0 :(得分:2)

这个计时器究竟是什么目的?我无法想象你会使用它,因为它不断重复每2秒运行一次。您可能遇到的一件事是Android的线程问题。该计时器任务在与Android UI使用的主线程不同的线程上运行。如果您正在触摸Android小部件或其他实例变量,那么您最终会遇到线程安全问题,如果您尝试这样做,Android通常会抛出异常。所以它归结为你试图用那个线程完成什么可能比创建这样的另一个线程更好。通常我们会使用Handler定期在主线程上运行任务,而不是像这样使用Timer,因为它引入了线程问题。

<强>更新

您刚刚在刚刚描述的内容中确认了严重的线程安全问题。线程安全的意思是你有两个线程可以同时读/写同一个内存位置。这是一个大问题。事实上,你自己承认,你的StringBuilder实例是在定时器线程和按钮回调之间共享的,这意味着你在读取StringBuilder时肯定会遇到线程安全问题。

您将会遇到持续不可预测的问题,并且在用户操作时您的代码永远不会稳定。首先,没有理由从另一个线程读取GPS,因为LocationManager会随着它的变化定期给你打电话。只需在调用时将其附加到StringBuilder或ArrayList上即可。 GPS回调在主线程上运行,因此读取该变量的按钮逻辑无法在修改该变量的同时发生。

您需要从代码中删除该计时器,并使用主线程完成所有工作。或者您必须同步对数据结构的访问。 Android中发生的大多数回调都在主线程上运行。因此,如果您只是将记录历史值的逻辑移动到那里的数据结构中,而不是在计时器中,那么你会没事的。您可能必须单独记录您尝试记录的其他任何内容,但您可以在按钮单击处理程序中将它们格式化为您的字符串。

您的NPE位于文件的第94行。如果不知道源代码的行号,我们无法帮助您。但这些是您遇到线程安全问题时遇到的问题类型。而且它们会让你发疯,因此有必要发出警告,并了解更多有关线程安全和安全控制的信息。

答案 1 :(得分: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@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()不知道主要的布局。