Почему попытка изменить TextView или показать тост в пределах timerTask заморозила мое приложение? - PullRequest
0 голосов
/ 02 января 2019
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()
    }
}

Я заметил, что если я напишу time.text внутри объекта timerTask или попытаюсь вызвать showToast(), мое приложение будет аварийно завершено.

Кроме того, когда я пытаюсь закомментировать "time.text = String.format("%d.%d", minutes,seconds)" и запускать приложение, просто используя оператор печати и исследуя logcat, оператор печати также не отображается.Я уже читал другие примеры людей, использующих объект Timer, так почему мой метод не работает?

Ответы [ 2 ]

0 голосов
/ 02 января 2019

Объект таймера является отдельным фоновым потоком, поэтому он не может напрямую обращаться к элементам пользовательского интерфейса (например, toast, textview). ссылка

Почему ваше приложение зависает?

Задачи таймера должны быть выполнены быстро. Если задача таймера занимает слишком много времени для выполнения, она «затягивает» поток выполнения задачи таймера. Это, в свою очередь, может задержать выполнение последующих задач, которые могут «сгруппироваться» и выполняться быстро, когда (и если) задача-нарушитель наконец завершится.

Наилучшим подходом для вышеперечисленного будет использование 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);
0 голосов
/ 02 января 2019

Toast является элементом пользовательского интерфейса, поэтому он должен работать на UI Thread, а не на background Thread

использовать runOnUiThread

runOnUiThread(new Runnable() {
        public void run()
        {
            Toast.makeText(yourContext, "Your Message", Toast.LENGTH_SHORT).show();
        }
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...