Android路由框架 - ARouter使用

引言

        现在Android项目一般都用的是组件化,组件化完全可以自己通过反射和注解写一套。

        在组件式开发时,有时在某个Module下想要使用其他Module的业务,很不方便,要不重新写一个,要么提到公共Module,ARouter直接可以解决这类问题。这就是--模块间Service通信调用。

但是,没必要重复造轮子。发现Arouter完全ok。就简单说说。

Arouter 支持模块间的路由、通信、解耦。

ARoutter-Github地址

基础使用

配置

在moudle_common中配置的

 defaultConfig {
        minSdk rootProject.ext.minSdkVersion
        targetSdk rootProject.ext.targetSdkVersion

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"


        //ARouter配置
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MOUDLE_NAME: project.getName()]
            }
        }

    }


dependencies {
...
    //路由ARouter
    api 'com.alibaba:arouter-api:1.5.2'
    annotationProcessor 'com.alibaba:arouter-compiler:1.5.2'
...
}

初始化

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        initARouter()
    }

    /**
     * 初始化ARouter
     */
    private fun initARouter() {
        if (BuildConfig.DEBUG) {
            ARouter.openLog()
            // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
            ARouter.openDebug()
        }
        ARouter.init(this)
    }

    override fun onTerminate() {
        super.onTerminate()
        //释放
        ARouter.getInstance().destroy()
    }
}

路由地址统一管理类  Constant

/**
 * 路由表
 */
object ARouterConstant {
    const val LOGIN_ACTIVITY = "/com/demo/loginActivity"
}

依赖注入

注意:这里路由地址 至少需要有两级,/xx/xx

@Route(path = ARouterConstant.LOGIN_ACTIVITY)
class TestActivity : BaseActivity(){


}
路由操作
    /**
     * 路由跳转 (不带参数)
     */
    findViewById<Button>(R.layout.activity_login).setOnClickListener{
        //路由跳转
        ARouter.getInstance().build("/arouter/TestActivity").navigation()
    }   


    /**
     * 路由跳转 (带参数)
     */
    private fun aRouterJump(){
        //带参数
        ARouter.getInstance().build(ARouterConstant.SECOND_ACTIVITY)
                .withLong("long",123l)
                .withString("string","路由")
                .withObject("object",new TestARouterEntry("时间",                 TimeUtils.getCurrentTime(TimeUtils.DateMode.SIMPLE_TIME_MODE)))
                .navigation()
    } 

代码混淆

-keep public class com.alibaba.android.arouter.routes.**{*;}
-keep public class com.alibaba.android.arouter.facade.**{*;}
-keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;}

#如果使用了 byType 的方式获取 Service,需要添加下面规则,保护接口
#emmm还没看到这种使用方法呢,这应该是进阶用法吧(这种就是自己定义接口继承自IProvider,然后实现自己的接口的方式使用IProvider)
-keep interface * implements com.alibaba.android.arouter.facade.template.IProvider

#如果使用了 单类注入 即 不顶用接口实现IPrvider,需要要添加规则,保护实现(哦哦 就是直接实现接口IProvider的类,不是通过自己定义接口继承自IProvider,然后在实现自己的接口)
#-keep class * implements com.alibaba.android.arouter.facade.template.IProvider

进阶--》模块间Service(业务逻辑)通信调用。

在组件式开发时,有时在某个Module下想要使用其他Module的业务,很不方便,要不重新写一个,要么提到公共Module,ARouter直接可以解决这类问题。

业务接口要声明在common公共Module中

申明接口内容

package com.sum.common.service

import android.content.Context
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.Observer
import com.alibaba.android.arouter.facade.template.IProvider

/**
 * @date   2023/3/25 11:29
 * @desc   登录服务相关接口
 * 只是定义了一个接口,提供了对外相关能力,其他模块只需要按需添加,需要在login模块实现
 */
interface ILoginService : IProvider {
    /**
     * 是否登录
     * @return Boolean
     */
    fun isLogin(): Boolean

    /**
     * 跳转登录页
     * @param context
     */
    fun login(context: Context)

    /**
     * 跳转隐私协议
     * @param context
     */
    fun readPolicy(context: Context)

    /**
     * 登出
     * @param context
     * @param lifecycleOwner
     * @param observer
     */
    fun logout(
        context: Context,
        lifecycleOwner: LifecycleOwner?,
        observer: Observer<Boolean>
    )

}

 接口的具体实现, 在具体module下

实现代码

package com.sum.login.service

import android.content.Context
import android.content.Intent
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import com.alibaba.android.arouter.facade.annotation.Route
import com.sum.common.constant.LOGIN_SERVICE_LOGIN
import com.sum.common.model.User
import com.sum.common.provider.UserServiceProvider
import com.sum.common.service.ILoginService
import com.sum.framework.log.LogUtil
import com.sum.framework.toast.TipsToast
import com.sum.login.login.LoginActivity
import com.sum.login.policy.PrivacyPolicyActivity
import com.sum.network.manager.ApiManager
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch

/**
 * @date   2023/3/25 13:41
 * @desc   提供对ILoginService接口的具体实现
 */
@Route(path = LOGIN_SERVICE_LOGIN)
class LoginService : ILoginService {

    /**
     * 是否登录
     * @return Boolean
     */
    override fun isLogin(): Boolean {
        return UserServiceProvider.isLogin()
    }

    /**
     * 跳转登录页
     * @param context
     */
    override fun login(context: Context) {
        context.startActivity(Intent(context, LoginActivity::class.java))
    }

    /**
     * 登出
     */
    override fun logout(
        context: Context,
        lifecycleOwner: LifecycleOwner?,
        observer: Observer<Boolean>
    ) {
        val scope = lifecycleOwner?.lifecycleScope ?: GlobalScope
        scope.launch {
            val response = ApiManager.api.logout()
            if (response?.isFailed() == true) {
                TipsToast.showTips(response.errorMsg)
                return@launch
            }
            LogUtil.e("logout${response?.data}", tag = "smy")
            observer.onChanged(response?.isFailed() == true)
            login(context)
        }
    }

    /**
     * 跳转隐私协议页
     * @param context
     */
    override fun readPolicy(context: Context) {
        context.startActivity(Intent(context, PrivacyPolicyActivity::class.java))
    }

    override fun init(context: Context?) {

    }
}

对外提供相关能力 provider

注意:provider在公共Module中

代码:

package com.sum.common.provider

import android.content.Context
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.Observer
import com.alibaba.android.arouter.facade.annotation.Autowired
import com.alibaba.android.arouter.launcher.ARouter
import com.sum.common.constant.LOGIN_SERVICE_LOGIN
import com.sum.common.service.ILoginService

/**
 * @date   2023/3/26 07:30
 * @desc   UserService提供类,对外提供相关能力
 * 任意模块就能通过LoginServiceProvider使用对外暴露的能力
 */
object LoginServiceProvider {
    //val loginService = ARouter.getInstance().build(LOGIN_SERVICE_LOGIN).navigation() as? ILoginService
    // [The inject fields CAN NOT BE 'private'!!! please check field [userService] in class [LoginServiceProvider]]
    @Autowired(name = LOGIN_SERVICE_LOGIN)
    lateinit var loginService: ILoginService

    init {
        ARouter.getInstance().inject(this)
    }

    /**
     * 是否登录
     * @return Boolean
     */
    fun isLogin(): Boolean {
        return loginService.isLogin()
    }

    /**
     * 跳转登录页
     * @param context
     */
    fun login(context: Context) {
        loginService.login(context)
    }

    /**
     * 跳转隐私协议
     * @param context
     */
    fun readPolicy(context: Context) {
        loginService.readPolicy(context)
    }

    /**
     * 登出
     * @param context
     * @param lifecycleOwner
     * @param observer
     */
    fun logout(
        context: Context,
        lifecycleOwner: LifecycleOwner?,
        observer: Observer<Boolean>
    ) {
        loginService.logout(context, lifecycleOwner, observer)
    }
}

模块提供服务的路由地址

代码

package com.sum.common.constant

/**
 * @date   2023/3/23 18:35
 * @desc   路由路径
 * 命名规则:/开头并且必须大于两级,/模块/分类/具体名称
 * 比如: /模块名称/组件[activity]/组件名称
 *       /模块名称/服务[service]/服务名称
 */

//**********************跳转相关**********************

/**
 * 登录模块
 */
//登录页面
const val LOGIN_ACTIVITY_LOGIN = "/login/activity/login"
//注册页面
const val LOGIN_ACTIVITY_REGISTER = "/login/activity/register"
//隐私协议界面
const val Login_ACTIVITY_POLICY = "/login/activity/policy"

/**
 * 首页模块
 */
//首页
const val MAIN_ACTIVITY_HOME = "/main/activity/home"

/**
 * 用户模块
 */
//设置界面
const val USER_ACTIVITY_SETTING = "/user/activity/setting"
//设置用户信息
const val USER_ACTIVITY_INFO = "/user/activity/info"
//我的收藏界面
const val USER_ACTIVITY_COLLECTION = "/user/activity/collection"

/**
 * 搜索模块-搜索页面
 */
const val SEARCH_ACTIVITY_SEARCH = "/search/activity/search"

/**
 * 视频模块
 */
const val VIDEO_ACTIVITY_PLAYER = "/video/activity/player"

/**
 * Demo模块
 */
//Navigation
const val DEMO_ACTIVITY_NAVIGATION = "/demo/activity/navigation"
//Lifecycle
const val DEMO_ACTIVITY_LIFECYCLE = "/demo/activity/lifecycle"
//ViewModel
const val DEMO_ACTIVITY_VIEWMODEL = "/demo/activity/viewmodel"
//LiveData
const val DEMO_ACTIVITY_LIVEDATA = "/demo/activity/livedata"

//**********************服务相关**********************

/**
 * 登录模块-登录服务
 */
const val LOGIN_SERVICE_LOGIN = "/login/service/login"

/**
 * 用户模块-用户服务
 */
const val USER_SERVICE_USER = "/user/service/user"

/**
 * 主页模块-主页
 */
const val MAIN_SERVICE_HOME = "/main/service/home"

/**
 * 搜索模块模块-搜索
 */
const val SEARCH_SERVICE_SEARCH = "/search/service/search"

使用

接下来就可以在其他Module去使用了,例如在MineModule下去使用loginModuleService,如下:

  LoginServiceProvider.login(requireContext())

这样就可以直接从MineModule调用loginModule的Service了(不用写登录这块逻辑了,很好的解耦)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值