Skip to content

RouterActivity 详解

Wiki edited this page Sep 8, 2019 · 3 revisions

功能

  1. 自动生成启动构造器。

  2. 支持 URL 启动 Activity。

  3. 支持配置多个path。

  4. 支持设置默认转场动画,支持设置单纯转场动画。

  5. 支持指定Flag。

  6. 支持多级跳转。

  7. 支持参数注入。

  8. 支持外部APP(浏览器)打开内部 Activity。

  9. 支持Flutter、Hybrid H5。

  10. 支持服务降级,可以通过服务降级主动拦截跳转、实现单Module运行调试。

为Activity增加注解

增加注解,然后点击顶部菜单 BuildMake Module XXX 就在 GActivityCenter 中生成构造器方法。

@RouterActivity("user")
class UserActivity : AppCompatActivity() {
    @RouterField
    var uid: Int? = null
    @RouterField
    var user: User? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        GRouter.inject(this)
        Log.e("uid", uid.toString())
    }
}

自动构造器调用

GActivityCenter.UserActivity().user(User(1,"Wiki")).start(context)

普通构造器调用

GRouter.getInstance().activityBuilder("user").put("uid",1).start(context)

URL方式调用

GRouter.getInstance().startActivity(context, "grouter://activity/user?uid=1")

支持配置多个path

如果要配置多个path,使用","分割即可。

@RouterActivity("user,user/user_detail")
class UserActivity : AppCompatActivity() {}

// grouter://activity/user?uid=1
// grouter://activity/user/user_detail?uid=1

设置默认转场动画

GActivityBuilder.defaultEnterAnim = R.anim.abc_fade_in
GActivityBuilder.defaultExitAnim = R.anim.abc_fade_out

设置单次转场动画

GActivityCenter.SettingsActivity()
.overridePendingTransition(R.anim.abc_fade_in, R.anim.abc_fade_out).start(this)

支持指定Flag

GActivityCenter.SettingsActivity().addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK).start(this)

多级跳转

作用是先跳转到A页面,然后从A页面跳转到B页面

GActivityCenter.SettingsActivity().nextNav(GActivityCenter.AboutUsActivity()).start(this)

URL拼接方式实现二级跳转,通过nextNav实现

grouter://activity/settings?nextNav=grouter%3a%2f%2factivity%2fabout_us

支持参数注入

只要使用了@RouterField的字段,调用GRouter.inject(this)方法,对应的字段就会自动解析intent.data和intent.extras的参数。

RouterField参数支持类型:int、long、float、double、boolean、Integer、Long、Double、Float、Boolean、String、int[]、long[]、float[]、double[]、boolean[]、String[]、可序列化List、可序列化Object

解析List和对象,必须在Application#onCreate设置GRouter.setSerialization(),根据自己项目的实际情况提供json序列化方法。

支持外部APP(浏览器)打开内部 Activity

配置AndroidManifest.xml

<activity android:name=".MainActivity">
<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
    <action android:name="android.intent.action.VIEW"/>
    <data android:scheme="grouter"/>
</intent-filter>
</activity>

在MainActivity#onCreate调用

String dataString = getIntent().getDataString();
if (dataString != null){
	GRouter.getInstance().startActivity(this,dataString);
}

就可以在外部的浏览器、或者其它APP,打开内部的Activity,建议不要为MainActivity配置@RouterActivity。

支持修改外部访问权限

exported 默认是 true,如果配置了path,允许从其它APP打开内部页面。如果页面存在安全要求,不允许从外部跳转,可以设置exported = false。

@RouterActivity("user",exported = false)
class UserActivity : AppCompatActivity() {
}
Hybrid H5
class WebViewActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_web_view)
        web_view.settings.javaScriptEnabled = true
        web_view.addJavascriptInterface(GRouterJavascriptInterface(this), "grouter")
        web_view.webChromeClient = WebChromeClient()
        web_view.loadUrl("file:///android_asset/grouter_example.html")
    }
}

Javascript

<script>
    function navPage(){
        window.grouter.startPage("grouter://activity/user?name=Wiki&uid=1")
    }
</script>

支持Flutter

创建插件类

class GRouterFlutterPlugin(val activity: Activity) : MethodChannel.MethodCallHandler {
    fun onMethodCall(methodCall: MethodCall, result: MethodChannel.Result) {
        if (methodCall.method.equals("startPage")) {
            val url = methodCall.argument("url")
            GRouter.getInstance().startActivity(this.activity, url)
        }
    }
    companion object {
        fun registerWith(registry: PluginRegistry) {
            val CHANNEL = "com.gourer/plugin"
            val registrar = registry.registrarFor(CHANNEL)
            val methodChannel = MethodChannel(registrar.messenger(), CHANNEL)
            val plugin = GRouterFlutterPlugin(registrar.activity())
            methodChannel.setMethodCallHandler(plugin)
        }
    }
}

在Activity中注册

class MainActivity : FlutterActivity() {
    override fun onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)
        GeneratedPluginRegistrant.registerWith(this)
        GRouterFlutterPlugin.registerWith(this)
    }
}

在Flutter中调用

static const grouterPlugin = const MethodChannel('com.gourer/plugin');
grouterPlugin.invokeMethod("startPage", {"url": "grouterdemo://activity/user?uid=1"})

服务降级

服务降级是使用拦截器实现,服务降级分为两种,主动降级和被动降级。主动降级是主动拦截让跳转重定向到新的页面,比如当用户点击了需要登录的服务可以用于判断用户未登录就提示登录引导用户跳转到登录页面,登录成功后继续跳转到目标页面。被动降级是由于跳转页面出错,开发者需要根据错误进行进一步处理,常用于单Module运行调试,当目标页面不在当前运行代码中,可以主动降级跳转到一个空页面,显示参数。

主动降级

如果未登录只允许打开LoginActivity和MainActivity

@RouterInterceptor
class LoginRouterInterceptor : GRouterInterceptor() {
    /**
     * 没有登录状态下可以访问的页面
     */
    private val visitorAccess = listOf(
            MainActivity::class.java.name,
            LoginActivity::class.java.name
    )
    private var loginUser: User? = null

    override fun init(context: Context, buildType: String?, params: MutableMap<String, Any>?) {
        super.init(context, buildType, params)
        loginUser = params?.get("loginUser") as User?
    }

    override fun process(request: ActivityRequest): Boolean {
        if (loginUser == null && !visitorAccess.contains(request.activityClass)) {
            Toast.makeText(request.context, "请登录", Toast.LENGTH_SHORT).show()
            request.onContinue(LoginActivity::class.java)
          	// request.onInterrupt(Exception("无访问权限"))
            // GActivityCenter.LoginActivity().start(request.context)
            return true
        }
        return super.process(request)
    }
}
被动降级

当跳转发生了错误的时候处理,可用用于提高APP的可用性,也可以用于实现单Module运行调试。

@RouterInterceptor
class LoginInterceptor : AbstractInterceptor() {
    override fun onError(request: ActivityRequest, exception: Exception): Boolean {
        exception.printStackTrace()
      	request.onContinue(ErrorActivity::class.java)
        return super.onError(request, exception)
    }
}