[英]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.