为什么尝试更改TextView或在timerTask中显示吐司会冻结我的应用程序?

时间:2019-01-02 04:38:49

标签: android kotlin

import android.annotation.SuppressLint
import android.os.Bundle
import android.support.design.widget.Snackbar
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_track_income.*
import java.util.*
import kotlin.concurrent.timerTask

class TrackIncome : AppCompatActivity() {

    @SuppressLint("SetTextI18n")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_track_income)

        val time: TextView = findViewById(R.id.time)
        val money: TextView = findViewById(R.id.money)
        val timer: Timer = Timer()  
        val calculateTime = timerTask {
            val milliseconds = System.currentTimeMillis()
            var seconds: Int = (milliseconds / 1000).toInt()
            val minutes = 1
            seconds %= 60
            print("seconds are " + seconds.toString()) 
            time.text = String.format("%d.%d", minutes,seconds)

        }
        Timer("timer", false).schedule(calculateTime,1000, 1000)

    }
    fun showToast(){
    Toast.makeText(this, "Its toast!", Toast.LENGTH_SHORT).show()
    }
}

我注意到,如果我在timerTask对象中写入time.text,或尝试调用showToast(),则我的应用程序将崩溃。

此外,当我尝试注释掉 "time.text = String.format("%d.%d", minutes,seconds)"并仅使用print语句运行应用程序并检查logcat,print语句也不会显示。我已经读过使用Timer对象的其他示例,所以为什么我的方法不起作用?

2 个答案:

答案 0 :(得分:2)

Timer对象是单个后台线程,因此它无法直接访问UI元素(如Toast,TextView)。 reference

  

为什么您的应用冻结了?

计时器任务应快速完成。如果计时器任务花费过多时间来完成,它将“占用”计时器的任务执行线程。反过来,这可能会延迟后续任务的执行,这可能会“累加”并在(如果有问题的)任务最终完成时迅速连续执行。

上面的最佳方法是在计时器完成后使用handler。喜欢,

    private Handler handler = new Handler();

并定义

handler = new Handler(getLooper()) {
        @Override
        public void handleMessage(Message msg) {
                Toast.makeText(this, "Its toast!", Toast.LENGTH_SHORT).show();
        }
    };

从您的计时器中调用它:

handler.sendMessage(messageObject);

答案 1 :(得分:1)

Toast是一个UI元素,因此它需要在UI Thread上运行,而不是在background Thread

上运行

使用runOnUiThread

runOnUiThread(new Runnable() {
        public void run()
        {
            Toast.makeText(yourContext, "Your Message", Toast.LENGTH_SHORT).show();
        }
    });
}