首页 > 解决方案 > 摆脱活动中重复的部分代码

问题描述

我是 Android 新手,所以在某些时候我意识到我有 20 个活动,其中有相同的部分。

app的整体结构如下:Activity1 -> Activity2 -> TaskActivity1 -> Activity3 -> Activity4 -> TaskActivity2 -> ...

因此,有 2 种类型的重复代码:用于简单活动和用于任务活动。

为简单的活动提供代码:

class Activity2 : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_2)
}

fun nextClick(view: View, ID: Int) {
    val intent3 = Intent(this, Activity3::class.java)
    startActivity(intent3)
    this.finish()
}

fun backClick(view: View){
    val intent1 = Intent(this, Activity1::class.java)
    startActivity(intent1)
    this.finish()
}

}

对于任务,只添加了 3 个按钮(用于答案)(因此,其中有 5 个:next、ans1、ans2、ans3、back)。此外,一些简单的活动在布局中没有后退按钮。

所以,显然我有大约 15 个活动具有相同的代码(而且看起来很糟糕)。

我试过了:

1)为活动创建一个类:

open class everyActivity(imageId: Int, nextActivity: Activity, prevActivity: Activity): AppCompatActivity() {

val imageId = imageId
val nextActivity = nextActivity
val prevActivity = prevActivity

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(imageId)
}

fun nextClick(view: View) {
    val intentNext = Intent(this, nextActivity::class.java)
    startActivity(intentNext)
    this.finish()
}

fun backClick(view: View){
    val intentPrev = Intent(this, prevActivity::class.java)
    startActivity(intentPrev)
    this.finish()
}

}

然后在活动中:

class Kadr1Activity : KadrActivity(R.layout.activity_kadr01, Kadr2Activity(), Kadr0InfoActivity()) {
}

它不起作用,应用程序显示白屏。

2)点击提取函数:

在 onClick 中无法传递 Activity 变量,因此提取函数无济于事。

3)坚持一项活动:

我不想每次点击都改变 ImageView 图片。正如我已经提到的,一些活动看起来不同(没有后退按钮),因此根据当前图像跟踪更改按钮并不方便。

4) 单一活动架构

我想在活动之间有动画,而且片段太复杂了(根据我找到的信息)。

那么,是否有可能摆脱我的应用程序中的重复代码?

将不胜感激任何可能的帮助,不知道如何解决这个问题

标签: androidandroid-studiokotlin

解决方案


如果我不能只交换片段并且必须执行单独的活动,我将创建一个活动类并打开它的多个实例,使用 Intent 附加功能来确定行为的细微差别,如下所示:

class MyActivity: AppCompatActivity()

    private val screen by lazy { 
        Screen.valueOf(intent.getStringExtra(SCREEN_KEY) ?: Screen.SCREEN_ONE.name)
        // The Elvis operator is to specifiy the default for when the activity
        // is the first instance from when the app was launched.
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.my_activity)
        imageView.setImageResource(screen.imageID)

        prepareButton(previousButton, Screen[screen.prevScreen])
        prepareButton(nextButton, Screen[screen.nextScreen])
    }

    private fun prepareButton(button: Button, targetScreen: Screen?) {
        if (targetScreen == null) {
            button.visibility = View.INVISIBLE
        } else {
            button.setOnClickListener { 
                val intent = Intent(this, MyActivity::class.java)
                intent.putExtra(SCREEN_KEY, targetScreen.name)
                startActivity(intent)
                finish()
           }
        }
    }
}

private const SCREEN_KEY = "SCREEN"

enum class Screen(val imageID: Int, val prevScreen: String?, val nextScreen: String?) {
    SCREEN_ONE(R.drawable.screenOneImg, null, "SCREEN_TWO"),
    SCREEN_TWO(R.drawable.screenTwoImg, "SCREEN_ONE", "SCREEN_THREE"),
    SCREEN_THREE(R.drawable.screenThreeImg, "SCREEN_TWO", null)

    companion object {
        operator fun get(name: String?) = name?.let { Screen.valueOf(it) }
    }
}

请注意,为简单起见,上面的示例代码就像您使用合成视图属性一样编写。如果不是,您将使用findViewById或视图绑定来获取视图引用。


编辑:

这是一种对初学者更友好的方法,无需枚举或惰性属性:

class MyActivity: AppCompatActivity()

    companion object {
        private const SCREEN_KEY = "SCREEN"
        private const lastScreenIndex = 2 // if there are three screens (counting starts at 0)
    }

    private var screen: Int = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.my_activity)

        screen = intent.getStringExtra(SCREEN_KEY) ?: 0 // 0 is default screen number
        val screenImageResource = when (screen) {
            0 -> R.drawable.screen_0_image
            1 -> R.drawable.screen_1_image
            else -> R.drawable.screen_2_image
        }
        imageView.setImageResource(screenImageResource )

        prepareScreen(previousButton, screen - 1)
        prepareScreen(nextButton, screen + 1)
    }

    private fun prepareButton(button: Button, targetScreen: Int) {
        if ((0..lastScreenIndex).contains(targetScreen)) {
            button.setOnClickListener { 
                val intent = Intent(this, MyActivity::class.java)
                intent.putExtra(SCREEN_KEY, targetScreen)
                startActivity(intent)
                finish()
           }
        } else {
            button.visibility = View.INVISIBLE
        }
    }
}

推荐阅读