12 android objective-c ios swift j2objc
假设您有一个跨平台应用程序.该应用程序在Android和iOS上运行.您在两个平台上的共享语言都是Java.通常,您将使用Java编写业务逻辑,并使用Java(适用于Android)和Objective-C(适用于iOS)编写所有UI特定部分.
通常,当您在跨平台,跨语言应用程序中实现MVP模式时,您将拥有Java中的Model和Presenter,并为您的演示者提供了一个Java界面.这样,您的共享Java演示者可以与您在平台特定部分上使用的任何视图实现进行通信.
让我们假设我们想要编写一个带有Java部分的iOS应用程序,以后可以使用相同的Android应用程序进行共享.以下是设计的图形表示:

在左侧有Java部分.在Java中,您可以编写模型,控制器以及视图界面.使用依赖注入进行所有连线.然后可以使用J2objc将Java代码转换为Objective-C .
在右侧,您有Objective-C部分.在这里,您UIViewController可以实现Java接口,这些接口转换为ObjectiveC协议.
问题:
我正在努力的是如何进行视图之间的导航.假设你在UIViewControllerA上,然后点击一个按钮,它会带你到UIViewControllerB.你会怎么做?
情况1:

您将按钮点击报告给UIViewControllerA的Java ControllerA(1),Java ControllerA调用链接到UIViewControllerB(3)的Java ControllerB(2).然后,您遇到的问题是Java Controller端不知道如何在Objective-C View层次结构中插入UIViewControllerB.您无法从Java端处理此问题,因为您只能访问View接口.
案例2:

您可以转换到UIViewControllerB,无论它是模态还是UINavigationController或其他(1).然后,首先需要正确的UIViewControllerB实例,该实例绑定到Java ControllerB(2).否则,UIViewControllerB无法与Java ControllerB(2,3)进行交互.当您拥有正确的实例时,您需要告诉Java ControllerB已经显示了View(UIViewControllerB).
我仍在努力解决如何处理不同控制器之间导航的问题.
如何在不同控制器之间建模导航并适当地处理跨平台视图更改?
我们是这样做的:
Activity/UIViewController没有任何操作背后的逻辑) -ActivityA直接打开ActivityB. ActivityB现在负责在需要时与应用程序共享逻辑层进行通信。ActivityA调用 some 的方法UseCase,该方法返回enumorpublic static final int并相应地采取一些操作 -OR-UseCase可以调用我们之前注册的方法ScreenHandler,该方法知道如何Activities使用一些提供的参数从应用程序中的任何位置打开公共资源。我是一家公司的首席开发人员,该公司使用 java 库来实现应用程序的模型、逻辑和业务规则,移动平台(Android 和 iOS)都使用 j2objc 实现这些库。
我的设计原则直接来自 Uncle Bob 和 SOLID,在设计包含组件间通信的整个应用程序时,我真的不喜欢使用 MVP 或 MVC,因为这样你就开始将每个应用程序Activity与 1 个且仅 1 个链接Controller,有时这是可以的,但大多数时候你最终会得到一个控制器的上帝对象,它的变化程度与 a 一样多View。这可能会导致严重的代码异味。
我最喜欢的处理方法(也是我认为最干净的方法)是将所有内容分解为UseCases每个处理应用程序中的 1 个“情况”。当然,您可以拥有一个Controller处理其中几个的任务UseCases,但它所知道的只是如何委托给这些任务UseCases,仅此而已。
此外,如果这个动作是一个简单的“带我到地图屏幕”或类似的任何动作,我看不出将每个动作链接Activity到逻辑层中的一个动作的原因。Controller的作用Activity应该是处理Views它所持有的内容,并且作为应用程序生命周期中唯一的“智能”事物,我认为它没有理由不能调用下一个活动本身的开始。
此外,Activity/UIViewController生命周期太复杂且彼此之间差异太大,无法由通用 java 库处理。我认为这是一个“细节”,而不是真正的“业务规则”,每个平台都需要实现和担心,从而使java lib中的代码更加坚实并且不易更改。
再说一次,我的目标是让应用程序的每个组件都尽可能遵循 SRP(单一职责原则),这意味着将尽可能少的东西链接在一起。
这是一个简单的“正常”内容的例子:
(所有例子完全是虚构的)
ActivityAllUsers显示模型对象项的列表。这些项目来自于后台线程中的调用AllUsersInteractor- a UseCase controller(反过来,它也由 java lib 处理,并在请求完成时分派到主线程)。用户单击此列表中的一项。在此示例中,ActivityAllUsers已经具有模型对象,因此打开ActivityUserDetail是对该数据模型对象的捆绑包(或其他机制)的直接调用。如果需要进一步的操作,新活动ActivityUserDetail负责创建和使用正确的操作。UseCases
复杂逻辑调用示例:
ActivityUserDetail有一个标题为“添加为朋友”的按钮,单击该按钮时会调用以下回调onAddFriendClicked方法ActivityUserDetail:
public void onAddFriendClicked() {
AddUserFriendInteractor addUserFriend = new AddUserFriendInteractor();
int result = addUserFriend.add(this.user);
switch(result){
case AddUserFriendInteractor.ADDED:
start some animation or whatever
break;
case AddUserFriendInteractor.REMOVED:
start some animation2 or whatever
break;
case AddUserFriendInteractor.ERROR:
show a toast to the user
break;
case AddUserFriendInteractor.LOGIN_REQUIRED:
start the log in screen with callback to here again
break;
}
}
Run Code Online (Sandbox Code Playgroud)
更复杂的调用示例
BroadcastReceiverAndroid 或 iOS 上的AAppDelegate会收到推送通知。它被发送到NotificationHandlerjava lib 逻辑层。在NotificationHandler构造函数中构造一次,App.onCreate()它需要ScreenHandler interface您在两个平台中实现的构造函数。解析此推送通知并在 中调用正确的方法来ScreenHandler打开正确的Activity.
底线是:View尽可能保持愚蠢,保持Activity足够聪明来处理自己的生命周期和处理自己的观点,并与自己的沟通controllers(复数!),其他所有内容都应该写下来(希望能够测试-首先 ;)) 在 java 库中。
使用这些方法,我们的应用程序目前在 java 库中运行大约 60-70% 的代码,下一次更新有望将其提高到 70-80%。
小智 1
我建议您使用某种插槽机制。与其他 MVP 框架使用的类似。
定义:槽是视图的一部分,可以在其中插入其他视图。
在演示者中,您可以根据需要定义任意数量的插槽:
GenericSlot slot1 = new GenericSlot();
GenericSlot slot2 = new GenericSlot();
GenericSlot slot3 = new GenericSlot();
Run Code Online (Sandbox Code Playgroud)
这些插槽必须在演示者视图中具有引用。您可以实施一个
setInSlot(Object slot, View v);
Run Code Online (Sandbox Code Playgroud)
方法。如果您setInSlot在视图中实现,那么视图可以决定如何包含它。
看看这里的插槽是如何实现的。
| 归档时间: |
|
| 查看次数: |
740 次 |
| 最近记录: |