2012-04-19 51 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