2017-01-31 70 views
1

我有一個for循環,我想在其中調用setText方法。這個工作沒有任何錯誤,除了在腳本完成運行之前文本沒有改變。我想要它做的是每次我調用setText方法時更改代碼。我在下面附上我的代碼,它應該是相當困難的。 code:定期更新的文本未顯示

package com.example.zoe.andone; 

import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.view.MenuItem; 
import android.view.View; 
import android.widget.TextView; 

import java.util.concurrent.TimeUnit; 

public class MainActivity extends AppCompatActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
    } 
    public void startLoop(View view) { 
     String string = getString(R.string.hello); 
     ((TextView)findViewById(R.id.hello)).setText("starting..."); 
     for (int i = 0; i < 10; i++) { 
      String updated = Integer.toString(i); 
      ((TextView)findViewById(R.id.hello)).setText(updated); 
      try { 
       Thread.sleep(250); 
      } catch(InterruptedException ex) { 
       Thread.currentThread().interrupt(); 
      } 
     } 
     ((TextView)findViewById(R.id.hello)).setText("done!"); 
    } 
} 
+0

使用'Handler'而不是調用'的Thread.sleep(250);'在主線程 –

+0

我不知道我跟隨。 – pudility

回答

1

這就是所謂的「丟幀」。

它的時間來學習!

纔去的答案,讓我們來解釋一下是怎麼回事。

您可能已經知道android的幀頻爲60fps(每秒60幀),這意味着屏幕每1/60秒都會呈現並顯示給用戶(爲了提供最佳定義) 。它通過在您的應用程序(以及其他需要渲染的地方)上運行一些渲染代碼來每隔1/60秒計算一下顯示的屏幕在這個特定的ms(它被稱爲幀)時的樣子。

然而,這樣做的代碼在UI線程上運行,而當渲染打勾球,如果你正在做什麼,Android框架簡單地丟棄該幀(它不會計算它)。 在你的情況Thread.sleep(250);是什麼原因導致它的持有250毫秒UI線程中的for循環您的每一次迭代的丟幀(所以它是250毫秒*(10 - 1),這是許多幀)。

刪除幀意味着在UI上看不到更新。

解決方案

而不是使用Thread.sleep(250);和丟幀的,你應該安排您的更新任務,以每250毫秒運行。而已。

private int i = 0; // Does the trick! 
public void startLoop(View view) { 
    String string = getString(R.string.hello); 
    ((TextView)findViewById(R.id.hello)).setText("starting..."); 
     final Handler handler = new Handler(); 
     handler.postDelayed(new Runnable() { 
      @Override 
      public void run() { 
       if (i < 10) { 
        String updated = Integer.toString(i); 
        i++; 
        updateHelloOnUiThread(updated); 
       } else { 
        updateHelloOnUiThread("done!"); 
        handler.removeCallbacksAndMessages(null); 
        i = 0; // For future usages 
       } 
      } 
     },250); 
} 

private void updateHelloOnUiThread(final String text) { 
    MainActivity.this.runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       ((TextView)findViewById(R.id.hello)).setText(text); 
      } 
    }); 
} 

進一步閱讀

Android UI : Fixing skipped frames

High Performance Android Apps, Chapter 4. Screen and UI Performance

+0

我正在使用你的代碼,但它給了我一個錯誤,說'變量'處理程序初始化'新Handler()。postDelayed(新的Runnable(){@Override公共無效的運行(){...'是多餘的'我不知道如何解決這個問題:( – pudility

+0

這就是當我懸停在它上面時會發生什麼,當我嘗試構建它時出現的錯誤是:錯誤:(28,21)錯誤:無法爲最終變量賦值i'感謝! – pudility

+0

涼,再次感謝您的幫助。它抱怨說我沒有通過'i'到函數的任何想法上? – pudility

1
this.runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       int globalTimer = 0; 

       int limitTimer = 10; 
       int i = 0; 

       // create Timer 
       Timer timer = new Timer(); 
       timer.schedule(new TimerTask() { 
        @Override 
        public void run() { 
         globalTimer++; 
         //run your code 
         ((TextView)findViewById(R.id.hello)).setText(i+""); 
         i++; 
         //check if globalTimer is equal to limitTimer 
         if (globalTimer == limitTimer) { 
          timer.cancel(); // cancel the Timer 
         } 
        } 

       }, 0, 250); 
      } 
     }); 
0

的問題是,你在UI線程調用了Thread.sleep。 如果線程正在休眠,則無法更新UI(屏幕上顯示的內容)。