什么是从-continuous-后台线程更新android ui的推荐方法?

时间:2012-08-20 12:56:24

标签: android multithreading user-interface

我已经阅读了很多关于这个主题的内容,以获得良好和彻底的困惑。我正在做一个运动追踪器应用程序,如RunKeeper,它可以追踪用户说话和运行的时间长度。我正在编程这个“锻炼”的主界面,它显示了一个类似秒表的布局,包括一个显示每秒更新时间的计时器,以及一个计数器,显示他到目前为止的运行距离。

我的问题是更新界面。我有一个秒表类跟踪时间,我根据gps位置计算距离,但我找不到在后台运行连续线程的建议方法,以固定的时间速率更新ui

据我所知,我应该在activity类中实现Handler.Callback接口,或者在Thread中有一个单独的Callback对象,但是我有点不知所措。如何让所有人一起工作。我都需要更新从秒表课程中得到的时间(简单的开始/停止时间计算,没有线程相关),以及根据onLocationChanged()中收到的位置计算的距离。

这是我的活动代码的精简版:

public class WorkoutActivity extends Activity implements OnClickListener, LocationListener
{
    private LocationManager locManager;
    private boolean workoutStarted = false;

    // The TextViews to update
    private TextView timeLabel;
    private TextView distanceLabel;

    private Stopwatch stopwatch;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        /*
            ... Interface initialisation
        */
        stopwatch = new Stopwatch();
    }

    private void startWorkout() {/* ...*/}
    private void stopWorkout()  {/* ...*/}
    private void pauseWorkout() {/* ...*/}
    private void resumeWorkout(){/* ...*/}
    public void onClick(View v) {/* ...*/}
    public void onLocationChanged(Location location){/* ...*/}
}

根据我在这里阅读的大多数答案我应该使用扩展handleMessage方法的Handler对象,但是现在(至少根据Lint中的警告)你必须使这些对象静态以避免内存泄漏。但是,这使得从Handler中直接访问和更改活动类中的其他私有对象有点奇怪。我想你可以通过在扩展Handler的类中创建需要影响参数的对象来解决这个问题,但我不知道,这感觉就像是一个“hack”(WorkoutActivity中的嵌套类):

static class TimeHandler extends Handler
{
    static final int MSG_START_TIMER = 1;
    static final int MSG_UPDATE_TIMER = 2;
    static final int MSG_STOP_TIMER = 3;

    private static final int REFRESH_RATE = 1000;

    private Stopwatch stopwatch;
    private TextView timeLabel;

    public TimeHandler(Stopwatch stopwatch, TextView label)
    {
        this.stopwatch = stopwatch;
        this.timeLabel = label;
    }

    @Override
    public void handleMessage(Message msg)
    {
        super.handleMessage(msg);

        switch(msg.what)
        {
            case MSG_START_TIMER:
                stopwatch.start();
                this.sendEmptyMessage(MSG_UPDATE_TIMER);
                break;
            case MSG_UPDATE_TIMER:
                timeLabel.setText(stopwatch.getElapsedTimeString());
                this.sendEmptyMessageDelayed(MSG_UPDATE_TIMER, REFRESH_RATE);
                break;
            case MSG_STOP_TIMER:
                this.removeMessages(MSG_UPDATE_TIMER);
                stopwatch.stop();
                timeLabel.setText(stopwatch.getElapsedTimeString());
                break;
        }           
    }

那么,任何人都可以解释从连续后台线程更新UI的“标准”方式吗?哦,抱歉这个长期的问题,只是想彻底。

2 个答案:

答案 0 :(得分:3)

使用runOnUiThread()

定义Runnable

private Runnable mRunnable = new Runnable() {
    @Override
    public void run() {
        mTextViewOne.setText("10 miles!");
        mTextViewTwo.setText("40 minutes!");
    }
};

在你的连续线程中:

runOnUiThread(mRunnable);

答案 1 :(得分:-1)

在AsyncTask中使用以下线程...我希望这对你有用....

   Handler mHandler;
private final Runnable mRunnable = new Runnable() {

        public void run() {
            Call your AsyncTask Class;;;;
            mHandler.postDelayed(mRunnable, 1000);
        }

    };