首页 > 解决方案 > How should I share Activity related code between multiple activities?

问题描述

I have several bits of functionality that I need in multiple activities in my app. They need to be able to access Activity methods, and in some cases override methods (e.g. I have some shared functionality to choose pictures from the Gallery that needs to handle onRequestPermissionsResult).

Any one of these is simple - I can create a XXXBase class, and then my Activity can derive from it. If I need more than one of these in my Activity though, I am limited by inheritance mechanics.

I could put all of this extra functionality in one common Base class that is used repeatedly, but that class could end up getting quite big and unwieldy.

Is there an alternative approach that I'm missing? I'm using Kotlin, if that opens up any extra possibilities.

标签: androidkotlin

解决方案


Given that you need to override certain framework methods, I think this actually would be a great case for using a headless Fragment. Using a Fragment, you can start Activitys, request permissions, handle the results, etc. Using this pattern, this Fragment can be attached to any Activity (or even another Fragment as a child). You of course could break down further classes that this headless Fragment relies on internally, but I would definitely suggest looking into a Fragment-based approach.

For example:

private const val REQUEST_CODE_PERMISSION: Int = 1

class MyUtilityFragment : Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        if (savedInstanceState == null) {
            // do permission request
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ): {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        // handle your permission result here
    }
}

Then in your Activity, you can just attach it in onCreate() and let it do its thing:

class MyActivity: AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        if (savedInstanceState == null) {
            supportFragmentManager.beginTransaction()
                .add(MyUtilityFragment(), "utility_fragment")
                .commitNow()
        }
    }
}

If you need to provide results back to the host, you can just designate an interface in your Fragment, and have the hosting parent Fragment or Activity implement that interface, and then retrieve it from the headless Fragment when needed:

private fun getCallback() : MyCallbackInterface {
    parentFragment?.takeIf { it is MyCallbackInterface }?.let { return it as MyCallbackInterface }
    return requireActivity() as MyCallbackInterface
}

推荐阅读