2012-11-14 129 views
0

我试图将PC Java程序移植到Android平台。 PC应用程序使用Swing.Timer每秒触发一次更新。关联的侦听器在被调用时从数据库获取新数据,然后使用Graphics2D更新/重绘屏幕。我学会了如何使用Android的Canvas绘制与PC应用程序相同的东西。现在我试图学习如何在Android中使用等价的Timer。不幸的是,在Android平台上看起来并不那么简单。有定时器,处理程序,报警管理器和AsyncTasks。看起来AsyncTasks和AlarmManagers更适合一次性(重型?)任务(对?错?)关于定时器和处理程序,我看到许多文章说不使用Timer,而是使用Handlers。我在网页上的某个地方的代码中找到了使用的方法,并尝试了它。它似乎应该做我想做的事情,但是当我点击停止按钮时它会挂起GUI。有谁知道它为什么这样做?Android Handler冻结GUI

由于次一百万 比尔

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    dateFormat = new SimpleDateFormat(dateFormatString); 
    mHandler = new Handler(); 
    mUpdateTimeTask = new MyRunnable(); 
    Button button = (Button) findViewById(R.id.start_button); 
    button.setOnClickListener(new MyStartListener()); 
    button = (Button) findViewById(R.id.stop_button); 
    button.setOnClickListener(new MyStopListener()); 
} 

class MyStartListener implements View.OnClickListener { 
    public void onClick(View v) { 
     if (startUptimeMillis == 0L) { 
      startUptimeMillis = SystemClock.uptimeMillis(); 
      mHandler.removeCallbacks(mUpdateTimeTask); 
      mHandler.postDelayed(mUpdateTimeTask, 100); 
     } 
    } 
}; 

class MyStopListener implements View.OnClickListener { 
    public void onClick(View v) { 
     mHandler.removeCallbacks(mUpdateTimeTask); 
    } 
}; 

class MyRunnable implements Runnable { 
    public void run() { 
     final long start = startUptimeMillis; 
     long millis = SystemClock.uptimeMillis() - start; 
     int seconds = (int) (millis/1000); 
     int minutes = seconds/60; 
     seconds = seconds % 60; 
     Calendar calendar = Calendar.getInstance(); 
     calendar.setTimeInMillis(System.currentTimeMillis()); 
     TextView tv = (TextView) findViewById(R.id.time_textView); 
     tv.setText(dateFormat.format(calendar.getTime())); 
     mHandler.postAtTime(this, (((minutes * 60) + seconds + 1) * 1000)); 
    } 
}; 

编辑: 的问题是,postAtTime需要一个绝对时间中开始,而不是一个延迟,这是我的例子是使用。 (See postAtTime here) 所以我更换了所有的计时码以上的下方,它做我想要的东西!!:

long millis = SystemClock.uptimeMillis(); 
mHandler.postAtTime(this, millis+1000); 

回答

1

我不明白这是如何挂您的应用程序,除非你的意思是启动按钮不工作了......也许你想添加到您的监听站:

public void onClick(View v) { 
    startUptimeMillis = 0l; // Reset startUptimeMillis 
    mHandler.removeCallbacks(mUpdateTimeTask); 
} 

至于定时器,AsyncsTask,等等......你是正确的,最好的方法程序在不久的将来Android的事件是一个Handler和Runnable。 AlarmManagers不适用于动画等快速回调,AsyncTasks适合重型计算。

我想一个提供一个简单的更新的Runnable:

class MyRunnable implements Runnable { 
    public void run() { 
     // You should make this a class variable and initialize it in onCreate(), 
     // there is no need to search for the same View every second. 
     TextView tv = (TextView) findViewById(R.id.time_textView); 

     final long now = System.currentTimeMillis(); 
     tv.setText(dateFormat.format(now)); 
     mHandler.postAtTime(this, 1000 - (now - start) % 1000); // Accounts for millisecond offsets over time 
     // mHandler.postDelayed(this, 1000); // Effected by minute offsets 
    } 
}; 
+0

要注意的是取决于Android版本,多个'AsyncTask's可以并行运行的串行而不是如你所期望的。 –

+1

感谢您的回复。抱歉耽搁了;我不得不离开城镇。 –