官术网_书友最值得收藏!

2.4 更新控制器層

在上一章,應(yīng)用控制器層的MainActivity類(lèi)的處理邏輯很簡(jiǎn)單:顯示定義在activity_main.xml文件中的布局對(duì)象,為兩個(gè)按鈕設(shè)置監(jiān)聽(tīng)器,響應(yīng)用戶(hù)點(diǎn)擊事件并創(chuàng)建toast消息。

既然現(xiàn)在有更多的地理知識(shí)問(wèn)題可以檢索與展示,MainActivity類(lèi)就需要更多的處理邏輯來(lái)讓GeoQuiz應(yīng)用的模型層與視圖層協(xié)作。

打開(kāi)MainActivity.kt文件,如代碼清單2-5所示,創(chuàng)建一個(gè)Question對(duì)象集合以及該集合的索引變量。

代碼清單2-5 增加Question對(duì)象集合(MainActivity.kt)

class MainActivity : AppCompatActivity() {

    private lateinit var trueButton: Button
    private lateinit var falseButton: Button

    private val questionBank = listOf(
            Question(R.string.question_australia, true),
            Question(R.string.question_oceans, true),
            Question(R.string.question_mideast, false),
            Question(R.string.question_africa, false),
            Question(R.string.question_americas, true),
            Question(R.string.question_asia, true))

    private var currentIndex = 0
    ...
}

這里,我們通過(guò)多次調(diào)用Question類(lèi)的構(gòu)造函數(shù),創(chuàng)建了Question對(duì)象集合。

(在較復(fù)雜的項(xiàng)目里,這類(lèi)集合的創(chuàng)建和存儲(chǔ)會(huì)單獨(dú)處理。在后續(xù)應(yīng)用開(kāi)發(fā)中,你會(huì)看到更好的模型數(shù)據(jù)存儲(chǔ)方式。現(xiàn)在,簡(jiǎn)單起見(jiàn),我們選擇在控制器層代碼中創(chuàng)建集合。)

要在屏幕上顯示一系列地理知識(shí)問(wèn)題,可以使用questionBank、currentIndex變量以及Question對(duì)象的存取方法。

如代碼清單2-6所示,首先給TextView和新Button添加屬性,然后引用它們,并設(shè)置TextView顯示當(dāng)前集合索引所指向的地理知識(shí)問(wèn)題(稍后會(huì)設(shè)置NEXT按鈕的點(diǎn)擊事件監(jiān)聽(tīng)器)。

代碼清單2-6 使用TextView(MainActivity.kt)

class MainActivity : AppCompatActivity() {

    private lateinit var trueButton: Button
    private lateinit var falseButton: Button
    private lateinit var nextButton: Button
    private lateinit var questionTextView: TextView
    ...
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        trueButton = findViewById(R.id.true_button)
        falseButton = findViewById(R.id.false_button)
        nextButton = findViewById(R.id.next_button)
        questionTextView = findViewById(R.id.question_text_view)

        trueButton.setOnClickListener { view: View ->
            ...
        }

        falseButton.setOnClickListener { view: View ->
            ...
        }

        val questionTextResId = questionBank[currentIndex].textResId
        questionTextView.setText(questionTextResId)
    }
}

保存所有文件,確保沒(méi)有錯(cuò)誤發(fā)生,然后運(yùn)行GeoQuiz應(yīng)用。可以看到,集合存儲(chǔ)的第一個(gè)問(wèn)題顯示在TextView上了。

現(xiàn)在來(lái)處理NEXT按鈕,為其設(shè)置監(jiān)聽(tīng)器View.OnClickListener。該監(jiān)聽(tīng)器的作用是讓集合索引遞增并相應(yīng)地更新TextView的文本內(nèi)容,如代碼清單2-7所示。

代碼清單2-7 使用新增的按鈕(MainActivity.kt)

override fun onCreate(savedInstanceState: Bundle?) {
    ...
    falseButton.setOnClickListener { view: View ->
        ...
    }

    nextButton.setOnClickListener {
        currentIndex = (currentIndex + 1) % questionBank.size
        val questionTextResId = questionBank[currentIndex].textResId
        questionTextView.setText(questionTextResId)

    }

    val questionTextResId = questionBank[currentIndex].textResId
    questionTextView.setText(questionTextResId)
}

注意到了嗎?同樣的questionTextView文字賦值代碼出現(xiàn)在了兩個(gè)不同的地方。參照代碼清單2-8,花點(diǎn)兒時(shí)間把這樣的公共代碼放到一個(gè)函數(shù)里,然后分別在nextButton監(jiān)聽(tīng)器里以及onCreate(Bundle?)函數(shù)的末尾調(diào)用它。后一個(gè)調(diào)用是為了初始化設(shè)置activity視圖中的文本。

代碼清單2-8 使用updateQuestion()封裝公共代碼(MainActivity.kt)

class MainActivity : AppCompatActivity() {
    ...
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        nextButton.setOnClickListener {
            currentIndex = (currentIndex + 1) % questionBank.size
            val questionTextResId = questionBank[currentIndex].textResId
            questionTextView.setText(questionTextResId)
            updateQuestion()
        }

        val questionTextResId = questionBank[currentIndex].textResId
        questionTextView.setText(questionTextResId)
        updateQuestion()
    }

    private fun updateQuestion() {
        val questionTextResId = questionBank[currentIndex].textResId
        questionTextView.setText(questionTextResId)
    }
}

運(yùn)行GeoQuiz應(yīng)用,驗(yàn)證新添加的NEXT按鈕。

如果一切正常,問(wèn)題應(yīng)該已經(jīng)完美顯示出來(lái)了。當(dāng)前,GeoQuiz應(yīng)用認(rèn)為所有問(wèn)題的答案都是true,下面著手修正這個(gè)邏輯錯(cuò)誤。同樣,為避免代碼重復(fù),我們將解決方案封裝在一個(gè)私有函數(shù)里。

要添加到MainActivity類(lèi)的函數(shù)如下:

private fun checkAnswer(userAnswer: Boolean)

該函數(shù)接受布爾類(lèi)型的變量參數(shù),判別用戶(hù)點(diǎn)擊了TRUE還是FALSE按鈕。然后,將用戶(hù)的答案同當(dāng)前Question對(duì)象中的答案做比較,判斷正誤,并生成一個(gè)toast消息反饋給用戶(hù)。

在MainActivity.kt文件中,添加checkAnswer(Boolean)函數(shù)的實(shí)現(xiàn)代碼,如代碼清單2-9所示。

代碼清單2-9 增加checkAnswer(Boolean)函數(shù)(MainActivity.kt)

class MainActivity : AppCompatActivity() {
    ...
    private fun updateQuestion() {
        ...
    }

    private fun checkAnswer(userAnswer: Boolean) {
        val correctAnswer = questionBank[currentIndex].answer

        val messageResId = if (userAnswer == correctAnswer) {
            R.string.correct_toast
        } else {
            R.string.incorrect_toast
        }

        Toast.makeText(this, messageResId, Toast.LENGTH_SHORT)
                .show()
    }
}

在按鈕的監(jiān)聽(tīng)器里,調(diào)用checkAnswer(Boolean)函數(shù),如代碼清單2-10所示。

代碼清單2-10 調(diào)用checkAnswer(Boolean)函數(shù)(MainActivity.kt)

override fun onCreate(savedInstanceState: Bundle?) {
    ...
    trueButton.setOnClickListener { view: View ->
        Toast.makeText(
            this,
            R.string.correct_toast,
            Toast.LENGTH_SHORT
        )
            .show()
        checkAnswer(true)
    }

    falseButton.setOnClickListener { view: View ->
        Toast.makeText(
            this,
            R.string.correct_toast,
            Toast.LENGTH_SHORT
        )
            .show()
        checkAnswer(false)
    }
    ...
}

運(yùn)行GeoQuiz應(yīng)用,確認(rèn)toast消息基于用戶(hù)點(diǎn)擊給出了正確反饋。

主站蜘蛛池模板: 剑川县| 沂南县| 遵义市| 长乐市| 登封市| 久治县| 康乐县| 手机| 林州市| 建湖县| 鹤岗市| 武强县| 朔州市| 瑞安市| 虹口区| 岳池县| 茶陵县| 郁南县| 张家港市| 石屏县| 黑河市| 监利县| 临泉县| 海淀区| 靖安县| 祁东县| 栾川县| 临清市| 神农架林区| 堆龙德庆县| 同心县| 龙山县| 华容县| 昌乐县| 大城县| 安新县| 常山县| 荆州市| 来凤县| 昌江| 晋城|