使用 Fragment 处理 onActivityResult

前言

对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)
        }
    }
}

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
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,012评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,628评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,653评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,485评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,574评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,590评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,596评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,340评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,794评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,102评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,276评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,940评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,583评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,201评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,441评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,173评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,136评论 2 352

推荐阅读更多精彩内容