簡體   English   中英

從單獨的線程更新高頻Android UI線程?

[英]High frequency Android UI Thread updating from a separate thread?

我試圖以較高的速度更新EditText,以便數字更流暢地流動。 但是我嘗試了技術和對象的不同組合,例如AsyncTask,帶有處理程序的Thread-> Runnable,帶有處理程序的Timer-> TimerTask,並且無論我設置了多長時間,它似乎都沒有任何比大約1秒更好的時間。

我認為可能是因為它必須經過消息泵,但我不確定。 有誰知道我如何獲得至少250到500毫秒的更新頻率? 較高的頻率將是可取的,但是那樣做。

更新2:我刪除了除count ++之外的所有內容; 並且我用此值更新了一個編輯文本,並且確實更新得非常快。 因此,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);      
}

df4android嘗試AsyncConnector,它可以非常快速地傳遞消息。

我無法重現此問題。 例如,使用以下代碼,更新速度非常快(在低端平板電腦上,更新速度非常快):

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),對我來說也存在性能問題。

使用Handler +延遲的Runnable或帶有onProgressUpdate()回調的AasyncTask來高頻更新EditText不會有任何問題。 我可以告訴您,我做了很多次,間隔為30到100毫秒,而且效果很好。

這就是讓我相信您做錯了其他事情的原因。 請發布您的代碼。

我的感覺是,您正在執行其他代碼,這些代碼在不合理的時間內(超過幾毫秒)阻塞了UI線程,因此-在UI線程上運行EditText更新的代碼部分受到限制。 阻塞主線程通常發生在執行IO文件操作,數據庫寫入,圖像解碼或其他繁重的計算時,因此,如果主線程上有其中之一,則應歸咎於它們。

原來,我最初沒有列出的功能是使用android.text.format.Time對象,該對象只有1秒的分辨率。 因此,這甚至不是很差的性能,只是對象每秒只經過一次,因此它不可能更快地更新。 下面是導致誤報的第一個函數,第二個是“修復”。 希望這將幫助任何錯誤地認為糟糕的表現是我的罪魁禍首的人。

//"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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM