¡Hola a todos! Hoy encontrarás un artículo sencillo que te dirá cómo escribir un simple juego de preguntas para dispositivos móviles en Kotlin. Aquí mostraré claramente cómo se ve Kotlin para el desarrollo móvil y ofreceré mis ideas sobre cómo estructurar dicho proyecto. Bueno, no te atormentaré con grafomanía, ¡adelante!
Ahora verá el esqueleto de una idea que ardió intensamente, pero que se extinguió rápidamente. A mi amigo diseñador y a mí se nos ocurrió la idea de hacer un juego móvil simple en formato de texto. Se planeó que el género fuera aventura, y el texto mezquino tenía que ser alimentado por imágenes únicas en un cierto estilo. Lamentablemente, las cosas no iban más allá del esqueleto de la aplicación, así que decidí hacerla pública. De repente, alguien encontrará nuevos pensamientos. De inmediato haré una reserva de que el proyecto difícilmente puede considerarse una decisión seria, y para aplicaciones realmente grandes, podría valer la pena considerar abstracciones más complejas. La aplicación debe percibirse como una especie de MVP.
Estructura de carpetas
Primero, hablemos de la estructura de carpetas. Es poco probable que haya algo innovador aquí, pero considero que la estructura de carpetas en un proyecto es una de las cosas más importantes e interesantes de la programación.
2 Activity, .
StartActivity , - (, “” ..).
MainActivity, - GameActivity, , .
Entity . json , , Entity.
dao ( data access object) , . , Runtime, , .
core , . , .
UI , , - . , presenter- activity.
MVP json-, . :
{
"id": 2,
"type": "Q",
"question": " . !",
"answers": [
{
"next_question_id": 5,
"answer": " "
},
{
"next_question_id": 3,
"answer": ", "
}
]
}
, :
Id - . . ,
type - . Q , "question" . F (Fail) S (Success). , ,
question - ,
answers - . 0 4 . , F S. , , ,
JSON assests. , . , , JSON , sqllite. , .
, , , . , . .
, runtime. Store.
public interface Store {
fun getAllQuestions(): List<Question>
fun getQuestionById(id: Int): Question
fun init(context: Context): Store
}
, . , - . MVP JSON-, , . , , , , sqllite . , - .
class StoreFactory {
companion object {
fun getStore(ctx: Context): Store {
return LocalStore().init(ctx)
}
}
}
. , . , , ANR. IO - . production , RX. , .
:
class Game {
private lateinit var store: Store
private lateinit var question: Question
fun init(context: Context) {
this.store = StoreFactory.getStore(context)
question = store.getQuestionById(1)
}
fun isGameEnd(): Boolean {
return isSuccess() || isFail()
}
fun isSuccess(): Boolean {
return question.isSuccess()
}
fun isFail(): Boolean {
return question.isFail()
}
fun chooseAnswer(numberOfAnswer: Int) {
val answer: Answer = question.getAnswers()[numberOfAnswer - 1]
question = store.getQuestionById(answer.getNextQuestionId())
}
fun getQuestion(): Question {
return question
}
}
2 : Store, , , . , ( type F S). , .
. , , . .
(Question.kt). :
fun getAnswers(): List<Answer> {
val list: MutableList<Answer> = ArrayList(this.answers)
val shouldAdd: Int = 4 - list.size
for (i in 1..shouldAdd) {
list.add(Answer("", -1))
}
return list
}
List 4 , , 2. id. , . , .
, 4 , . , presenter:
private fun updateView() {
if (game.isGameEnd()) {
showEndGame()
return
}
activity.setQuestion(game.getQuestion().getText())
val answers: List<Answer> = game.getQuestion().getAnswers()
answers.forEachIndexed {idx, answer -> activity.setAnswer(idx + 1, answer.getText())}
}
fun chooseAnswer(number: Int) {
game.chooseAnswer(number)
updateView()
}
, StartActivity, ( ) Intent:
private fun showEndGame() {
val intent = Intent(activity, StartActivity::class.java).apply {
putExtra(StartActivity.RESULT_MESSAGE, game.getQuestion().getText())
}
activity.startActivity(intent)
}
, production-ready. , . MVP, , . , :
. ,
UI- , .
,
json - , loader
json sqllite