Muh*_*uja 5 navigation android module
我正在尝试实现一个单独的导航模块来在 android 库模块之间导航,重点关注可扩展性、可重用性和模块独立性。我的应用程序架构与此示例类似:
我目前的做法
NavigatorInterface1-为每个库定义
2- 实现NavigatorInterface中的每一个NavigationModule。(当然导航模块会了解所有其他库模块,但这并不重要,因为它不会被重用)
以下是我上述架构的示例代码:
: 验证
|-- 登录活动
|-- 报名活动
|-- AuthNavigator
public class LoginActivity extends AppCompatActivity {
private NavigatorCoordinator navigator; // how do I achieve this injection, without using Dagger etc.
.....
private void signup(){
navigator.NavigateToSignup(this);
}
private void profile(){
navigator.NavigateToProfile(this);
}
.....
}
public class SignupActivity extends AppCompatActivity {
private NavigatorCoordinator navigator; // how do I achieve this injection, without using Dagger etc.
.....
private void login(){
navigator.NavigateToLogin(this);
}
private void profile(){
navigator.NavigateToProfile(this);
}
.....
}
public interface AuthNavigator {
void NavigateToLogin(Context context);
void NavigateToRegister(Context context);
}
Run Code Online (Sandbox Code Playgroud)
:轮廓
|-- 个人资料活动
|-- 简介导航
public class ProfileActivity extends AppCompatActivity {
private NavigatorCoordinator navigator; // how do I achieve this injection, without using Dagger etc.
.....
private void about(){
navigator.NavigateToAbout(this);
}
.....
}
public interface ProfileNavigator {
void NavigateToProfile(Context context);
}
Run Code Online (Sandbox Code Playgroud)
:关于
|-- 关于活动
|-- 关于Navigator
public class AboutActivity extends AppCompatActivity {
private NavigatorCoordinator navigator; // how do I achieve this injection, without using Dagger etc.
.....
private void profile(){
navigator.NavigateToProfile(this);
}
.....
}
public interface AboutNavigator {
void NavigateToAbout(Context context);
}
Run Code Online (Sandbox Code Playgroud)
上述方法试图消除同一模块内:auth以及两个模块:profile&之间的循环依赖:about。下面是 的实现:navigation。
:导航
|-- 导航器
public class Navigator implements AuthNavigator, ProfileNavigator, AboutNavigator {
@Override
public void NavigateToLogin(Context context) {
context.startActivity(new Intent(context, LoginActivity.class));
}
@Override
public void NavigateToSingup(Context context) {
context.startActivity(new Intent(context, SignupActivity.class));
}
@Override
public void NavigateToProfile(Context context) {
context.startActivity(new Intent(context, ProfileActivity.class));
}
@Override
public void NavigateToAbout(Context context) {
context.startActivity(new Intent(context, AboutActivity.class));
}
}
Run Code Online (Sandbox Code Playgroud)
问题:
1-我相信,我需要实现NavigatorCoordinatorin:navigation模块,但我该怎么做呢?这个实现有什么例子吗?
2-如何在不使用 Deggar 或任何其他框架的情况下注入NavigatorCoordinator驻留在不同的每个 Activity 类中的依赖项?modules我们可以使用类来实现吗Application?如果可以,请给出实现示例?
3- 如何从任何库设置Launcher活动,例如:LoginActivity?
4-如何以启动特定活动的方式:navigation从模块调用模块,例如: ?:appProfileActivity
5-这是实现可重用性、可扩展性和关注点分离的良好模块间导航方法吗?
6-还有其他类似且好的方法吗?有代码示例吗?文章链接?
PS:请不要告诉我使用导航架构组件。
小智 0
实际上,您可以为此应用一些面向对象的解决方法。首先,您可以考虑在公共模块内声明一个导航器接口。由于每个模块都是独立的并且彼此不了解,因此您需要遵循更通用的方法。您可以定义类似导航器界面的东西
interface Navigator {
fun navigate(activity: Activity, bundle: Bundle)
}
Run Code Online (Sandbox Code Playgroud)
现在考虑在不引用它的情况下打开活动,但使用密钥。您应该有一个工厂来将给定的键映射到活动导航器。您可以认为您想用密钥打开 AboutActivity,因为您没有它的引用。键可以是整数,也可以是类包名称,这并不重要。我将坚持使用包名称作为关键。
interface NavigatorFactory {
fun of(packageName: String): Navigator
}
Run Code Online (Sandbox Code Playgroud)
并且在活动内部导航时,您需要以某种方式获取这些导航器。理想的方法是使用应用程序类,因为您在任何活动中都可以引用它。因此我们定义了一个接口来应用于应用程序类。
interface NavigatorApplication {
fun getNavigatorFactory(): NavigatorFactory
}
Run Code Online (Sandbox Code Playgroud)
所以我们在公共模块中结束了我们的实现。让我们继续应用程序模块。您需要开始声明这些接口的实现
class AboutActivityNavigator: Navigator {
public void navigate(Activity activity, bundle: Bundle) {
val intent = Intent(activity, AboutActivity::class.java)
activity.startActivity(intent, bundle)
}
}
Run Code Online (Sandbox Code Playgroud)
返回这些 Navigator 实例的工厂实现。
object NavigatorFactoryImpl: NavigatorFactory {
fun get(key: String): Navigator {
when(key) {
is "com.example.AboutActivity" -> AboutActivityNavigator()
}
}
}
Run Code Online (Sandbox Code Playgroud)
为工厂提供模块可识别的接口。这样模块就可以到达接口并接收工厂实例。
class Application: NavigatorApplication {
val factoryImpl = NavigatorFactoryImpl()
fun getNavigatorFactory() = factoryImpl
}
Run Code Online (Sandbox Code Playgroud)
我们也完成了应用程序模块。现在,您可以导航到任何模块中所需的每个活动。
class ProfileActivity: Activity() {
fun navigateToAboutActivity() {
(application as? NavigatorApplication)?
.getNavigatorFactory()
.of("com.example.AboutActivity")
.navigate(this, Bundle())
}
}
Run Code Online (Sandbox Code Playgroud)
最终一切都是有代价的。您的模块是完全独立的。但不要忘记,您仍在传递一些硬编码密钥来打开活动。此外,您无法保证类型安全。如果您在捆绑包中传递类似 ("page-id",34) 的键值,您可能永远不知道目标活动是否接受相同的键和相同的类型。
如果您将来有基于单活动的架构,您还可以查看Jetpack Navigation by Google
| 归档时间: |
|
| 查看次数: |
733 次 |
| 最近记录: |