从单独的线程更新高频Android UI线程?

时间:2014-06-15 05:48:29

标签: java android multithreading

我试图以高速率更新EditText,以便数字流动更顺畅。但是我尝试过不同的技术和对象组合,例如AsyncTask,Thread-> Runnable with a handler,Timer-> TimerTask with a handler,无论我设置多长时间,它都没有&# 39;似乎比约1秒更好。

我认为这可能是因为它必须通过消息泵,但我无法确定。有谁知道如何获得至少250到500毫秒的更新频率?更高的频率是可取的,但那样做。

更新2: 我评论了除了计数++以外的一切;并且我使用此值更新其中一个编辑文本,它确实更新非常快。因此updateUi()中发生的事情正在减慢它的速度。我只是不知道是什么。

更新1: 我切换了实时使用的SharedPreferences,我正在使用它来测试原语,以防万一这是问题的一部分。表现似乎是一样的。定期发生的唯一想法是在计时器上运行的updateUi()函数。代码如下,这是我期望快速更新的内容,但不是:

private void updateUi() {

    lastDate = cal;
    cal = Calendar.getInstance();

    synchronized(cal) {

        //if the current date is greater than the last stored date
        if(compareDates(cal, lastDate) > 0 && count == 0) {
            //disable timer
            calorieTimer.cancel();
            //dereference timer...probably not necessary
            calorieTimer = null;
            double bankBmr = currentBmr.getBMR() * 
                    activityLevelMultipliers[activityLevelSpinner.getSelectedItemPosition()];
            metrics.calorieBank += (int)bankBmr - metrics.caloriesEaten;
            prefsEditor.putInt("CALORIE_BANK", metrics.calorieBank);
            prefsEditor.putInt("CALORIES_EATEN", 0);
            prefsEditor.commit();
            metrics.caloriesEaten = 0;
            //update lastDate to prevent multiple calorie banking
            lastDate = cal;
            count++;
            Log.e("updateUi()", "count #" + count);
            //set up timer again
            setupCalorieTimer();
        }

        caloriesEatenEditText.setText("" + metrics.caloriesEaten);
        caloriesRemainingEditText.setText(String.format("%d", (int)activeBmr - metrics.caloriesEaten));
        bankEditText.setText("" + metrics.calorieBank);
        estimatedWeightEditText.setText(String.format("%.2f", metrics.currentWeight - metrics.calorieBank / 3500.0)) ;
        //update the time
        time.setToNow();
        //update calories available
        caloriesAvailableEditText.setText(
                String.format("%.2f", activeBmr * percentageOfDay(time) - metrics.caloriesEaten));

    } //End synchronized(cal)

} //End updateUi()

private void setupCalorieTimer() {              
    //create handler to post update back to ui thread
    final Handler handler = new Handler();          

    calorieTimer = new Timer();

    calorieTimer.schedule(new TimerTask() {
        @Override
        public void run() {
            //post to ui thread
            handler.post(new Runnable() {
                @Override
                public void run() {
                    updateUi();
                }                   
            });     
        }           
    }, 0, 50);      
}

4 个答案:

答案 0 :(得分:1)

df4android尝试AsyncConnector,它会非常快速地传递消息。

答案 1 :(得分:1)

我无法重现这个问题。通过以下代码更新非常快(例如在低端平板电脑上快速模糊):

package com.mycompany.myapp42;

import android.app.*;
import android.os.*;
import android.widget.*;
import java.text.*;
import java.util.*;

public class MainActivity extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        final TextView tv = (TextView) findViewById(R.id.textView);
        new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    while (true)
                    {
                        runOnUiThread(new Runnable()
                            {
                                @Override
                                public void run()
                                {
                                    tv.setText(new SimpleDateFormat("HH:mm:ss.SSS").format(new Date()));
                                }
                            });
                        try
                        {
                            Thread.sleep(10);
                        }
                        catch (InterruptedException e)
                        {}
                    }
                }
            }).start();
    }
}

修改

如果软键盘(SwiftKey)可见,我也会遇到性能问题。

答案 2 :(得分:1)

使用处理程序+延迟EditTextRunnable并使用AasyncTask回调,无法在高频率onProgressUpdate()更新任何问题。 我可以告诉你,我做了很多次,间隔为30-100毫秒,效果很好。

这就是让我相信你做错了什么的原因。 请发布您的代码。

我的感觉是你正在执行其他代码阻止UI线程的时间不合理(超过几毫秒),并且正因为如此 - 运行EditText更新的代码部分UI线程是有限的。阻止主线程通常在执行IO文件操作,数据库写入,图像解码或其他繁重的计算时发生,所以如果你在主线程中有一个 - 那就是责备。

答案 3 :(得分:1)

事实证明,我最初没有列出的函数是使用只有1秒分辨率的android.text.format.Time对象。因此,即使性能不佳,也只是该对象每秒只运行一次,因此无法更快地更新。下面是导致误报的第一个函数,第二个函数是" fix"。希望这会帮助那些错误地认为表现不佳的人像我一样的罪魁祸首。

//"caused" the problem
private double percentageOfDay(Time time) {
    //factor the hour
    double percentage = time.hour / 24f;
    //factor the minute
    percentage += time.minute / 1440f;
    //factor the second
    percentage += time.second / 86400f;     

    return percentage;
}

//This fixed the problem
private double percentageOfDay(Calendar cal) {
    //factor the hour
    double percentage = cal.get(Calendar.HOUR) / 24f;
    //factor the minute
    percentage += cal.get(Calendar.MINUTE) / 1440f;
    //factor the second
    percentage += cal.get(Calendar.SECOND) / 86400f;
    //factor the millisecond
    percentage += cal.get(Calendar.MILLISECOND) / 86400000f;

    return percentage;
}