什么是推荐的方式从-continuous-后台线程更新Android的用户界面? [英] What is recommended way to update android ui from a -continuous- background thread?

查看:110
本文介绍了什么是推荐的方式从-continuous-后台线程更新Android的用户界面?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我读过不够好,关于这个问题得到很好彻底糊涂了。我在做一个锻炼跟踪器的应用程序,如RunKeeper,跟踪多久多远用户已经说了,跑。我在编程这个锻炼,它显示了一个秒表般的布局其中包括一个计时器,显示其每秒更新一次时间的主界面的过程和计数器显示多远,他跑这么远。<​​/ P>

我的问题是更新的接口。我有时间秒表类保持​​跟踪,和我计算基于GPS位置的距离,但我茫然地寻找推荐的方式来运行一个连续螺纹在更新UI上的一个固定时间率的背景

据我已经能够告诉我应该既可以实现Handler.Callback接口在活动课,或者有一个单独的回调对象有一个线程在一起,但我有点无所适从上如何让这一切一起工作。余都需要更新显示的时间,我从我的秒表类得到(简单的启动/停止时间计算,没​​有什么线程有关的),并且基于该位置计算出的距离中onLocationChanged接收()。

下面是我的活动code一个精简版:

 公共类WorkoutActivity扩展活动实现OnClickListener,LocationListener的
{
    私人LocationManager locManager;
    私人布尔workoutStarted = FALSE;

    //该TextViews更新
    私人TextView的timeLabel;
    私人TextView的distanceLabel;

    私人秒表秒表;

    @覆盖
    公共无效的onCreate(包savedInstanceState)
    {
        / *
            ...接口初始化
        * /
        秒表=新的秒表();
    }

    私人无效startWorkout(){/ * ... * /}
    私人无效stopWorkout(){/ * ... * /}
    私人无效pauseWorkout(){/ * ... * /}
    私人无效resumeWorkout(){/ * ... * /}
    公共无效的onClick(视图v){/ * ... * /}
    公共无效onLocationChanged(位置定位){/ * ... * /}
}
 

根据大多数的答案我读过在这里我应该使用扩展的handleMessage方法的Handler对象,但现在(至少根据皮棉警告),你必须做出这样的对象静以避免内存泄漏。那不过,让人有点奇怪直接从处理程序中访问和更改活动类的其他私人物品。我想你可以通过你需要影响扩大处理程序中的一类参数对象解决这个问题,但我不知道,感觉有点黑客(内WorkoutActivity嵌套类):

 静态类TimeHandler扩展了Handler
{
    静态最终诠释MSG_START_TIMER = 1;
    静态最终诠释MSG_UPDATE_TIMER = 2;
    静态最终诠释MSG_STOP_TIMER = 3;

    私有静态最终诠释REFRESH_RATE = 1000;

    私人秒表秒表;
    私人TextView的timeLabel;

    公共TimeHandler(秒表计时秒表,TextView的标签)
    {
        this.stopwatch =秒表;
        this.timeLabel =标签;
    }

    @覆盖
    公共无效的handleMessage(信息MSG)
    {
        super.handleMessage(MSG);

        开关(msg.what)
        {
            案例MSG_START_TIMER:
                stopwatch.start();
                this.sendEmptyMessage(MSG_UPDATE_TIMER);
                打破;
            案例MSG_UPDATE_TIMER:
                timeLabel.setText(stopwatch.getElapsedTimeString());
                this.sendEmptyMessageDelayed(MSG_UPDATE_TIMER,REFRESH_RATE);
                打破;
            案例MSG_STOP_TIMER:
                this.removeMessages(MSG_UPDATE_TIMER);
                stopwatch.stop();
                timeLabel.setText(stopwatch.getElapsedTimeString());
                打破;
        }
    }
 

所以,任何人都可以请解释从一个连续的后台线程更新UI的标准的方式?哦,对不起长的问题,只是想彻底。

解决方案

使用<一个href="http://developer.android.com/reference/android/app/Activity.html#runOnUiThread%28java.lang.Runnable%29"相对=nofollow> runOnUiThread()

定义的Runnable

 私人可运行mRunnable =新的Runnable(){
    @覆盖
    公共无效的run(){
        mTextViewOne.setText(10哩!);
        mTextViewTwo.setText(40.分钟!);
    }
};
 

在你的连续螺纹:

  runOnUiThread(mRunnable);
 

I've read well enough on the subject to get well and thoroughly confused. I'm doing a workout tracker app such as RunKeeper, which tracks how long and how far the user has been say, running. I'm in the process of programming the main interface of this "workout" which shows a stopwatch-like layout which includes both a timer showing the time which is updated every second, and a counter showing how far he's run so far.

My problem is updating the interface. I have a stopwatch class keeping track of the time, and I calculate the distance based on gps locations, but I'm at a loss to find the recommended way to run a continuous thread in the background that updates the ui on a fixed time rate.

As far as I've been able to tell, I should either be implementing the Handler.Callback interface in the activity class, or have a separate Callback object together with a Thread, but I'm sort of at a loss on how to get it all to work together. I both need to update the time shown that I get from my stopwatch class (simple start/stop time calculation, nothing thread-related), and the distance calculated based on the locations received in onLocationChanged().

Here's a stripped down version of my Activity code:

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){/* ...*/}
}

According to most answers I've read around here I should use a Handler object extending the handleMessage method, but nowadays (at least according to the warning in Lint) you have to make such objects static to avoid memory leaks. That however, makes it a bit strange to directly access and change the other private objects in the activity class from within the Handler. I suppose you could solve this by making the objects you need to affect parameters in a class extending Handler, but I dunno, it feels like a bit of a "hack" (nested class within 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;
        }           
    }

So, could anyone please explain the "standard" way of updating the UI from a continuous background thread? Oh, and sorry for the long question, just wanted to be thorough.

解决方案

Use runOnUiThread().

Define a Runnable:

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

Inside your continuous thread:

runOnUiThread(mRunnable);

这篇关于什么是推荐的方式从-continuous-后台线程更新Android的用户界面?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆