使用 Fragment 处理 onActivityResult

1,230 阅读7分钟

前言

对Activity和Fragment之间的跳转封装处理,在Activity/Framgent中用法基本一样。每个函数基本上都对应着一个扩展函数,方便调用。实现方式有很多种,可以自由组合,实际使用时按需求使用。

api列表

createIntent            :生成跳转的Intent并添加参数(可选)
addPair                 :Intent 添加参数
startActivityK          :跳转
startActivityForResultK :带回调的跳转
browse                  :打开浏览器
share                   :生调用分享,只能分享文本
email                   :发送邮件
makeCallPermission  :拨打电话,需要权限
makeCall                :拨打电话
sendSMS                 :发送短信

常规跳转startActivity,没有回调

  1. 不带任何参数
IntentKtx.startActivityK(this,TvActivity::class.java)
IntentKtx.startActivityK<TvActivity>(this)
startActivityK<TvActivity>()//扩展函数
  1. 前两个是封装函数,第3个是扩展函数,可以直接在Activity好Fragment中调用,在其他地方只要有Context也可以调用扩展函数,方式如下:
context.startActivityK<TvActivity>()
  1. 使用Intent传参
 val intent = Intent(this,TvActivity::class.java)
 intent.putExtra("tv","one")
 intent.putExtra("hai","hai---")
 IntentKtx.startActivityK(this,intent)
  1. 对应的扩展函数:
  val intent = Intent(this,TvActivity::class.java)
        intent.putExtra("tv","one")
        intent.putExtra("hai","hai---")
//        IntentKtx.startActivityK(this,intent)
        startActivityK(intent)
  1. 更简便的写法:
Intent(this,TvActivity::class.java)
    .addPair("tv" to "one", "hai" to "two")
    ?.let { startActivityK(it) }
  1. 使用Pair传参
//函数
IntentKtx.startActivityK(this,TvActivity::class.java,"tv" to "one","hai" to "hello")
//扩展函数
startActivityK(TvActivity::class.java,"tv" to "one","hai" to "hello")
//函数
IntentKtx.startActivityK<TvActivity>(this,"tv" to "one","hai" to "hello")
//扩展函数
startActivityK<TvActivity>("tv" to "one","hai" to "hello")

startActivityForResult跳转

使用Fragment处理onActivityResult,网络上有很多开源库都是使用Fragment处理封装。回调result就是onActivityResult里的resultCode, intent就是回传的数据。

  1. 无参跳转
ActivityHelper.init(this)
    ?.startActivityForResult(TvActivity::class.java){reuslt,intent->
        Log.e(TAG, "btnMainStartListener: $reuslt ---- ${intent?.getStringExtra("key")}");
    }
  1. 对应的扩展函数:
startActivityForResultK(TvActivity::class.java){ reuslt ,intent->
            Log.e(TAG, "btnMainStartListener: $reuslt ---- ${intent?.getStringExtra("key")}");
        }
  1. 无参跳转,使用内联函数
ActivityHelper.init(this)
    ?.startActivityForResult<TvActivity>{reuslt,intent->
        Log.e(TAG, "btnMainStartListener: $reuslt ---- ${intent?.getStringExtra("key")}");
    }
  1. 对应的扩展函:
startActivityForResultK<TvActivity>{result ,intent->
      Log.e(TAG, "btnMainStartListener: $result ---${intent?.getStringExtra("key")}")
  }
  1. 使用Intent携带参数跳转
  //带参数跳转,数据放在 intent 里面
/*       val intent2 = Intent(this,TvActivity::class.java)
       intent2.putExtra("tv","key one")
       ActivityHelper.init(this)
           ?.startActivityForResult(intent2){result ,intent->
               Log.e(TAG, "btnMainStartListener: $result ---- ${intent?.getStringExtra("key")}")
           }*/
  //扩展函数
     /* val intent2 = Intent(this,TvActivity::class.java)
      intent2.putExtra("tv","key one")
      startActivityForResultK(intent2){result ,intent->
          Log.e(TAG, "btnMainStartListener: $result ---- ${intent?.getStringExtra("key")}")
      }*/
  1. 使用Pair带参跳转
 //pair 传值
      /*ActivityHelper.init(this)
          ?.startActivityForResult(TvActivity::class.java,
          "tv" to "key one", "hai" to "key two"){result ,intent->
              Log.e(TAG, "btnMainStartListener: $result ---- ${intent?.getStringExtra("key")}")
          }*/
 //扩展函数
/*      startActivityForResultK(TvActivity::class.java,
          "key" to "key one", "key2" to "key two"){result ,intent->
          Log.e(TAG, "btnMainStartListener: $result ---- ${intent?.getStringExtra("key")}")
      }*/
  1. 使用Pair带参跳转,内联函数
//方法一  
ActivityHelper.init(this)
      ?.startActivityForResult(TvActivity::class.java,{result ,intent->
               Log.e(TAG, "btnMainStartListener: $result ---- ${intent?.getStringExtra("key")}")
           },"key" to "key one", "key2" to "key two")
 //方法二          
 ActivityHelper.init(this)
            ?.startActivityForResult<TvActivity>("key" to "key one", "key2" to "key two"){result ,intent->
                Log.e(TAG, "btnMainStartListener: $result ---- ${intent?.getStringExtra("key")}")
            }
 //扩展函数
  startActivityForResultK<TvActivity>("tv" to "key one", "hai" to "key two"){result ,intent->
          Log.e(TAG, "btnMainStartListener: $result ---- ${intent?.getStringExtra("key")}")
      }

在目标Activity/Fragment使用

在目标Activity/Fragment界面,创建函数实现跳转。这样方便其他人调用跳转,而且不用关心传值的key,也方便以后同意修改。这里面无法直接使用扩展函数,有些方法虽然可以使用,但是并不比扩展函数更方便,这里给出示例,,实现方式有很多种,可以自由组合,实际使用时按需求使用。

companion object{
    //这里使用不了扩展函数,简单几个示例,不带回调跳转
    //不传参数一般也没必要在这里写,直接使用扩展函数更方便
    fun starter(context: Context){
        IntentKtx.startActivityK(context,TvActivity::class.java)
    }
    fun starter2(context: Context){
        IntentKtx.startActivityK<TvActivity>(context)
    }
    //一般这种没有必要写在这里,直接用扩展函数跳转就好了
    fun starter(context: Context,vararg pair: Pair<String,Any?>){
        IntentKtx.startActivityK<TvActivity>(context,*pair)
    }
    //这里比较实现这种情况,key值定好,调用的地方直接传对应的参数就行了
    fun starter(context: Context,tv: String?,hai: String?){
        val intent = Intent(context,TvActivity::class.java)
        intent.addPair("tv" to tv, "hai" to hai)
        IntentKtx.startActivityK(context,intent)
    }
    //带回调跳转
    fun starter(context: Context?,callback: ((Int, Intent?) -> Unit)?){
        ActivityHelper.init(context)
            ?.startActivityForResult<TvActivity>(callback)
    }
    //回调也一样,这里比较适合这种情况
    fun starter(context: Context?,tv: String?,hai: String?,callback: ((Int, Intent?) -> Unit)?){
        val intent = Intent(context,TvActivity::class.java)
        intent.addPair("tv" to tv, "hai" to hai)
        ActivityHelper.init(context)
            ?.startActivityForResult(intent,callback)
    }
       //写成下面这样更简洁
       fun starter(context: Context, tv: String?, hai: String?, callback: ((Int, Intent?) -> Unit)?){
            val intent = context.createIntent<TextViewActivity>("tv" to tv, "hai" to hai)
            ActivityHelper.init(context)
                ?.startActivityForResult(intent,callback)
        }
        //或者写成这样,实现方式有很多,可以自由组合
        fun starter2(context: Context, tv: String?, hai: String?, callback: ((Int, Intent?) -> Unit)?){
            val intent = context.createIntent<TextViewActivity>("tv" to tv, "hai" to hai)
            context.startActivityForResultK(intent,callback)
        }
}

其他界面调用示例:

        //调用跳转类的跳转方法
//        TvActivity.starter(this)
//        TvActivity.starter(this,"one","two")
        //回调跳转
//        TvActivity.starter(this,"one","two"){result,intent ->
//            Log.e(TAG, "btnMainStartListener: $result ---- ${intent?.getStringExtra("key")}")
//        }

源码

内容比较简单,只有三个类,约400行代码。复制到代码中即可使用。

  • RouterFragment
class RouterFragment : Fragment() {

    private val mCallbacks: SparseArray<((Int, Intent?) -> Unit)?> = SparseArray()

    private val mCodeGenerator: Random = Random()

    companion object {
        fun newInstance(): RouterFragment? {
            return RouterFragment()
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //防止重复创建
        retainInstance = true
    }

    fun startActivityForResult(intent: Intent, callback: ((Int, Intent?) -> Unit)?) {
        val requestCode = makeRequestCode()
        mCallbacks.put(requestCode, callback)
        startActivityForResult(intent, requestCode)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        //处理返回的结果
        val callback = mCallbacks[requestCode]
        mCallbacks.remove(requestCode)
        callback?.run {
            invoke(resultCode, data)
        }
    }

    /**
     * 随机生成唯一的requestCode,最多尝试10次
     * @return
     */
    private fun makeRequestCode(): Int {
        var requestCode: Int
        var tryCount = 0
        do {
            requestCode = mCodeGenerator.nextInt(0x0000FFFF)
            tryCount++
        } while (mCallbacks.indexOfKey(requestCode) >= 0 && tryCount < 10)
        return requestCode
    }


}
  • IntentKtx
object IntentKtx {
    fun addPair(intent: Intent, vararg params: Pair<String, Any?>) {
        params.forEach {
            when (val value = it.second) {
                null -> intent.putExtra(it.first, null as Serializable?)
                is Int -> intent.putExtra(it.first, value)
                is Long -> intent.putExtra(it.first, value)
                is CharSequence -> intent.putExtra(it.first, value)
                is String -> intent.putExtra(it.first, value)
                is Float -> intent.putExtra(it.first, value)
                is Double -> intent.putExtra(it.first, value)
                is Char -> intent.putExtra(it.first, value)
                is Short -> intent.putExtra(it.first, value)
                is Boolean -> intent.putExtra(it.first, value)
                is Serializable -> intent.putExtra(it.first, value)
                is Bundle -> intent.putExtra(it.first, value)
                is Parcelable -> intent.putExtra(it.first, value)
                is Array<*> -> when {
                    value.isArrayOf<CharSequence>() -> intent.putExtra(it.first, value)
                    value.isArrayOf<String>() -> intent.putExtra(it.first, value)
                    value.isArrayOf<Parcelable>() -> intent.putExtra(it.first, value)
                    else -> throw Exception("Intent extra ${it.first} has wrong type ${value.javaClass.name}")
                }
                is IntArray -> intent.putExtra(it.first, value)
                is LongArray -> intent.putExtra(it.first, value)
                is FloatArray -> intent.putExtra(it.first, value)
                is DoubleArray -> intent.putExtra(it.first, value)
                is CharArray -> intent.putExtra(it.first, value)
                is ShortArray -> intent.putExtra(it.first, value)
                is BooleanArray -> intent.putExtra(it.first, value)
                else -> throw Exception("Intent extra ${it.first} has wrong type ${value.javaClass.name}")
            }
        }
    }

    /**
     * 不带回调跳转相关
     */
    fun startActivityK(context: Context?, clazz: Class<*>) {
        context?.startActivity(Intent(context, clazz))
    }

    inline fun <reified T> startActivityK(context: Context?) {
        context?.startActivity(Intent(context, T::class.java))
    }

    fun startActivityK(context: Context?, intent: Intent) {
        context?.startActivity(intent)
    }

    fun startActivityK(context: Context?, clazz: Class<*>, vararg params: Pair<String, Any?>) {
        context?.run {
            val intent = Intent(this, clazz)
            intent.addPair(*params)
            startActivity(intent)
        }
    }

    inline fun <reified T> startActivityK(context: Context?, vararg params: Pair<String, Any?>) {
        context?.run {
            val intent = Intent(this, T::class.java)
            intent.addPair(*params)
            startActivity(intent)
        }
    }
}
/**
 *生成跳转的Intent并添加参数
 * @param T
 * @param pair
 */
inline fun <reified T> Context.createIntentStart(vararg pair: Pair<String, Any?>) =
    Intent(this, T::class.java).apply {
        addPair(*pair)
    }

/**
 *生成Intent添加参数,也可以不添加
 */
fun Context.createIntent(vararg pair: Pair<String, Any?>) = Intent().addPair(*pair)

fun Intent?.addPair(vararg params: Pair<String, Any?>): Intent? {
    return this?.also { IntentKtx.addPair(it, *params) }
}

/**
 * 不带回调,无参跳转
 */
fun Context?.startActivityK(clazz: Class<*>) {
    this?.startActivity(Intent(this, clazz))
}

inline fun <reified T> Context?.startActivityK() {
    this?.startActivity(Intent(this, T::class.java))
}

/**
 * 不带回调,带参跳转
 */
fun Context?.startActivityK(intent: Intent) {
    this?.startActivity(intent)
}

fun Context?.startActivityK(clazz: Class<*>, vararg pair: Pair<String, Any?>) {
    this?.run {
        val intent = Intent(this, clazz)
        startActivity(intent.addPair(*pair))
    }
}

inline fun <reified T> Context?.startActivityK(vararg pair: Pair<String, Any?>) {
    this?.run {
        val intent = Intent(this, T::class.java)
        startActivity(intent.addPair(*pair))
    }
}

/**
 * 不带回调,无参跳转
 */
fun Fragment?.startActivityK(clazz: Class<*>) {
    this?.startActivity(Intent(activity, clazz))
}

inline fun <reified T> Fragment?.startActivityK() {
    this?.startActivity(Intent(activity, T::class.java))
}

/**
 * 不带回调,带参跳转
 */
fun Fragment?.startActivityK(intent: Intent) {
    this?.startActivity(intent)
}

fun Fragment?.startActivityK(clazz: Class<*>, vararg pair: Pair<String, Any?>) {
    this?.run {
        val intent = Intent(activity, clazz)
        startActivity(intent.addPair(*pair))
    }
}

inline fun <reified T> Fragment?.startActivityK(vararg pair: Pair<String, Any?>) {
    this?.run {
        val intent = Intent(activity, T::class.java)
        startActivity(intent.addPair(*pair))
    }
}


/**
 * Context扩展函数跳转
 */
fun Context?.startActivityForResultK(clazz: Class<*>, callback: ((Int, Intent?) -> Unit)?) {
    ActivityHelper.init(this)?.startActivityForResult(clazz, callback)
}

fun Context?.startActivityForResultK(intent: Intent, callback: ((Int, Intent?) -> Unit)?) {
    ActivityHelper.init(this)?.startActivityForResult(intent, callback)
}

inline fun <reified T> Context?.startActivityForResultK(noinline callback: ((Int, Intent?) -> Unit)?) {
    ActivityHelper.init(this)?.startActivityForResult<T>(callback)

}

fun Context?.startActivityForResultK(
    clazz: Class<*>,
    vararg pair: Pair<String, Any?>,
    callback: ((Int, Intent?) -> Unit)?
) {
    ActivityHelper.init(this)
        ?.startActivityForResult(clazz, callback, *pair)
}

inline fun <reified T> Context?.startActivityForResultK(
    vararg pair: Pair<String, Any?>,
    noinline callback: ((Int, Intent?) -> Unit)?
) {
    ActivityHelper.init(this)
        ?.startActivityForResult<T>(callback, *pair)
}


/**
 * 上述方法在 fragment 中扩展
 */
fun Fragment?.startActivityForResultK(clazz: Class<*>, callback: ((Int, Intent?) -> Unit)?) {
    ActivityHelper.init(this?.context)?.startActivityForResult(clazz, callback)
}

fun Fragment?.startActivityForResultK(intent: Intent, callback: ((Int, Intent?) -> Unit)?) {
    ActivityHelper.init(this?.context)?.startActivityForResult(intent, callback)
}

inline fun <reified T> Fragment?.startActivityForResultK(noinline callback: ((Int, Intent?) -> Unit)?) {
    ActivityHelper.init(this?.context)?.startActivityForResult<T>(callback)
}

fun Fragment?.startActivityForResultK(
    clazz: Class<*>,
    vararg pair: Pair<String, Any?>,
    callback: ((Int, Intent?) -> Unit)?
) {
    ActivityHelper.init(this?.context)
        ?.startActivityForResult(clazz, callback, *pair)
}

inline fun <reified T> Fragment?.startActivityForResultK(
    vararg pair: Pair<String, Any?>,
    noinline callback: ((Int, Intent?) -> Unit)?
) {
    ActivityHelper.init(this?.context)
        ?.startActivityForResult<T>(callback, *pair)
}
  • ActivityHelper
class ActivityHelper private constructor(activity: FragmentActivity) {
    private val TAG = "MMMK"
    var mContext: Activity? = null
    private var mRouterFragment: RouterFragment? = null

    init {
        mContext = activity
        mRouterFragment = getRouterFragment(activity)
    }

    companion object {
//        fun init(activity: FragmentActivity?): ActivityHelper? {
//            if (activity != null) return ActivityHelper(activity)
//            return null
//        }

        fun init(context: Context?): ActivityHelper? {
            if (context is FragmentActivity) return ActivityHelper(context)
            return null
        }
    }


    private fun getRouterFragment(activity: FragmentActivity): RouterFragment? {
        var routerFragment: RouterFragment? = findRouterFragment(activity)
        if (routerFragment == null) {
            //创建 fragment,加入当前 activity
            routerFragment = RouterFragment.newInstance()
            val sfm = activity.supportFragmentManager
            sfm.beginTransaction().add(routerFragment!!, TAG).commitAllowingStateLoss()
            sfm.executePendingTransactions()
        }
        return routerFragment
    }

    private fun findRouterFragment(activity: FragmentActivity): RouterFragment? {
        //通过 tag 获取 fragment
        return activity.supportFragmentManager.findFragmentByTag(TAG) as RouterFragment?
    }


    /**
     * 对Intent跳转,不带参数
     */
    fun startActivityForResult(
        clazz: Class<*>,
        callback: ((Int, Intent?) -> Unit)?
    ) {
        mContext?.run {
            val intent = Intent(this, clazz)
            startActivityForResult(intent, callback)
        }
    }

    inline fun <reified T> startActivityForResult(noinline callback: ((Int, Intent?) -> Unit)?) {
        mContext?.run {
            val intent = Intent(mContext, T::class.java)
            startActivityForResult(intent, callback)
        }
    }

    /**
     *带参数跳转
     * @param T
     * @param pair
     * @param callback
     */
    inline fun <reified T> startActivityForResult(
        vararg pair: Pair<String, Any?>,
        noinline callback: ((Int, Intent?) -> Unit)?
    ) {
        if (mContext == null) return
        val intent = Intent(mContext, T::class.java)
        IntentKtx.addPair(intent, *pair)
        startActivityForResult(intent, callback)
    }

    inline fun <reified T> startActivityForResult(
        noinline callback: ((Int, Intent?) -> Unit)?,
        vararg pair: Pair<String, Any?>
    ) {
        if (mContext == null) return
        val intent = Intent(mContext, T::class.java)
        IntentKtx.addPair(intent, *pair)
        startActivityForResult(intent, callback)
    }

    fun startActivityForResult(
        clazz: Class<*>,
        vararg pair: Pair<String, Any?>,
        callback: ((Int, Intent?) -> Unit)?
    ) {
        mContext?.run {
            val intent = Intent(this, clazz)
            IntentKtx.addPair(intent, *pair)
            startActivityForResult(intent, callback)
        }
    }

    fun startActivityForResult(
        clazz: Class<*>,
        callback: ((Int, Intent?) -> Unit)?,
        vararg pair: Pair<String, Any?>
    ) {
        mContext?.run {
            val intent = Intent(this, clazz)
            IntentKtx.addPair(intent, *pair)
            startActivityForResult(intent, callback)
        }
    }

    /**
     * 对Intent跳转,带参数
     * @param intent  参数提取放入intent中
     * @param callback
     */
    fun startActivityForResult(intent: Intent, callback: ((Int, Intent?) -> Unit)?) {
        mRouterFragment?.run {
            startActivityForResult(intent, callback)
        }
    }


}

导入依赖

不想复制更省事的方法,直接依赖即可。依赖如下: Github上面有详细的文档。 最新版

    allprojects {
        repositories {
            ...
            maven { url 'https://www.jitpack.io' }
        }
    }

dependencies {
            implementation 'com.github.KiWiLss:LUtils:1.1.0'
    }

使用前要调用,获取到 Context:

object LUtilsConfig{

    lateinit var mContext: Context
    fun init(context: Context) {
        mContext = context
    }