kotlin和java语言

    科技2026-09-24  19

    kotlin和java语言

    In this article, I will show you a simple pattern that you can use in just about any programming language or platform that supports enums, dictionaries, sealed classes, etc. Our source code examples for today are Java & Kotlin, but the idea remains the same across all similar languages.

    在本文中,我将向您展示一个简单的模式,您可以在支持枚举,字典,密封类等的任何编程语言或平台中使用。我们今天的源代码示例是Java&Kotlin,但思想仍然是所有类似语言都一样。

    主要思想:事件驱动编程 (The Main Idea: Event Driven Programming)

    Every time your user interacts meaningfully with your application, that interaction can be considered as an Event. In fact, any interaction with your application, even ones that are fired internally such as when the device reconnects to a network (i.e. system services), can be considered events. Today we will look mostly at UI events, but understand that I use this pattern in many ways throughout the back end as well. In the next article, I will talk about that in detail, along with how to use a functional approach to event handling.

    每次用户与应用程序进行有意义的交互时,该交互都可以视为事件。 实际上,与应用程序的任何交互,即使是内部触发的交互,例如设备重新连接到网络(即系统服务)时,也可以视为事件。 今天,我们将主要研究UI事件,但要理解,我在后端也以多种方式使用了这种模式。 在下一篇文章中,我将详细讨论这一点,以及如何使用功能性方法进行事件处理。

    Events can be modeled in many ways, but a common and easy object oriented approach is to use some kind of data structure such as an enum or sealed class. In either case, these tools are designed to create a restricted and specific set of values/types, which makes them appropriate for modelling a finite set of events.

    事件可以通过多种方式进行建模,但是一种常见且简单的面向对象方法是使用某种数据结构,例如枚举或密封类。 无论哪种情况,这些工具都旨在创建受限制的特定值/类型集,这使其适合于对有限事件集进行建模。

    用Java建模事件 (Modelling Events In Java)

    Below we have a feature of an application:

    下面我们有一个应用程序的功能:

    Based on all the different ways the user can interact with this feature, I have created a Java class with a nested enum to represent said events:

    基于用户与该功能交互的所有不同方式,我创建了一个带有嵌套枚举的Java类来表示所述事件:

    public class TaskViewEvent { private final Event event; private final Object value; public TaskViewEvent(Event event, Object value){ this.event = event; this.value = value; } public Event getEvent() { return event; } public Object getValue() { return value; } public enum Event { ON_COLOR_BUTTON_CLICK, ON_COLOR_SELECTED, ON_DONE_CLICK, ON_ICON_SELECTED, ON_START}}

    Now, you would probably want to create an abstract class and then subclass it for each feature, but this application was small enough that I did not really care.

    现在,您可能想要创建一个抽象类,然后为每个功能将其子类化,但是此应用程序很小,我并不在意。

    If you don’t know how to use interfaces, abstract classes, or even how to use inheritance as a mechanism for abstraction, then you will want to watch my comprehensive introduction to Java programming.

    如果您不知道如何使用接口,抽象类,甚至不知道如何将继承用作抽象机制,那么您将希望观看我对Java编程的全面介绍。

    When it comes time to actually unpack these events and handle them, we can set up a single entry point which cleans up your code and makes it easier to test. In this case, I did create an abstract class which will be implemented by any class which has the duty of handling events (obviously):

    当需要真正解压缩这些事件并进行处理时,我们可以设置一个入口点,以清理您的代码并使其更易于测试。 在这种情况下,我确实创建了一个抽象类,该类将由负责处理事件的任何类(显然)实现:

    public abstract class BaseViewLogic<T> { //you can remove this and use an interface instead if you do not need cancellation private boolean isCancelled = false; /** * If the View indicates that it is to be destroyed, we want to inform the Logic class * so that it can avoid calling back to a null fragment/activity. */public void onCancel(){ isCancelled = true; } public abstract void onViewEvent(T event);}

    Next, we have the class which actually handles the events. This would be your Controller, Presenter, ViewModel or whatever else you want really.

    接下来,我们有实际处理事件的类。 这将是您的Controller,Presenter,ViewModel或您真正想要的其他任何东西。

    I use the generic name Logic, which is a result of the fact that I have transcended three layer architecture dogma and built my own architecture to suit the project requirements at hand.

    我使用通用名称Logic,这是因为我已经超越了三层体系结构教条,并构建了自己的体系结构以适应手头的项目需求。

    public class TaskViewLogic extends BaseViewLogic<TaskViewEvent> { private ITaskViewContract.View view; private ITaskViewContract.ViewModel vm; private ITaskStorage storage;public TaskViewLogic(ITaskViewContract.View view, ITaskViewContract.ViewModel vm, ITaskStorage storage) { this.view = view; this.vm = vm; this.storage = storage; } @Override public void onViewEvent(TaskViewEvent event) { //code like this make me miss Kotlin syntax... switch (event.getEvent()) { case ON_START: onStart(); break; case ON_COLOR_BUTTON_CLICK: view.showColorPickerSheet(); break; case ON_COLOR_SELECTED: onColorSelected((COLOR) event.getValue()); break; case ON_DONE_CLICK: updateStorage(); break; case ON_ICON_SELECTED: onIconSelected( (ICON) event.getValue() ); break; } } //...}

    There are several things happening in that code:

    该代码中发生了几件事:

    Firstly, note that we have specified our TaskViewEvent class as the Generic of our abstract class:

    首先,请注意,我们已将TaskViewEvent类指定为抽象类的泛型:

    public class TaskViewLogic extends BaseViewLogic<TaskViewEvent>

    That is very important, and if you do not understand what we did here, I must once again suggest my Java course; you will not be disappointed with it.

    这非常重要,如果您不了解我们在这里所做的工作,那么我必须再次建议我的Java课程; 您不会对此感到失望。

    Secondly, we are using a switch statement which selects for different enum values. This is how we actually fork the execution of the program based on what event has occured.

    其次,我们使用switch语句选择不同的枚举值。 这就是我们根据发生的事件实际分叉程序执行的方式。

    Thirdly, when we want to get the value out of our event class (assuming that event needs a value), then we simply call event.getValue(), and cast it to whatever the value is supposed to be. Unfortunately because Java is annoying this way, you have to be careful about NullPointerException and ClassCastException.

    第三,当我们想从事件类中获取值时(假设该事件需要一个值),则只需调用event.getValue() ,并将其强制转换为该值即可。 不幸的是,由于Java令人讨厌,因此您必须注意NullPointerException和ClassCastException。

    Finally, you may wonder how I actually forward events to my event handler class. Each View holds a reference to an abstract EventHandler class:

    最后,您可能想知道我如何将事件实际转发到事件处理程序类。 每个视图都包含对抽象EventHandler类的引用:

    class TaskView extends Fragment { private final BaseViewLogic<TaskViewEvent> logic; private ImageButton doneButton; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_manage_task, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); doneButton.setOnClickListener( v -> { logic.onViewEvent(new TaskViewEvent( TaskViewEvent.Event.ON_DONE_CLICK, null )); } ); /*for those who cannot read lambda expressions, this is just a simpler way of writing doneButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { ... } }); */ }}

    Want To Watch Me Build The App That These Samples Are From?

    是否想观看我构建这些示例来自的应用程序?

    在Kotlin中建模事件 (Modelling Events In Kotlin)

    Now that you have the general idea, we will just talk implementation here. This is all much easier to do in Kotlin, as is typically the case. Sealed Classes are pretty much designed for this kind of purpose:

    现在您已经有了大致的想法,我们将在这里讨论实现。 通常情况下,这在Kotlin中都容易完成。 密封类几乎是为此目的而设计的:

    sealed class MovementEvent { object OnShowVideoClick : MovementEvent() object OnImageClick : MovementEvent() data class OnStart(val movementId: String?): MovementEvent()}

    No need to mess around with creating an enum and a wrapper class around it; if your event needs a value, use a data class; otherwise use an object.

    无需为创建枚举和包装类而费心; 如果您的事件需要一个值,请使用数据类; 否则使用一个对象。

    Again, handling this event is much prettier and more concise than in Java. Kotlin automatically casts it for you, and the syntax is just better overall:

    同样,与Java相比,处理此事件更漂亮,更简洁。 Kotlin会自动为您转换它,并且语法整体上更好:

    override fun handleEvent(eventType: MovementEvent) { when (eventType){ is MovementEvent.OnStart -> getMovement(eventType.movementId) is MovementEvent.OnImageClick -> onImageClick() is MovementEvent.OnShowVideoClick -> showYoutubePlayer() }}

    Again, we use either an interface or an abstract class in the View in order to forward our events:

    同样,我们在View中使用接口或抽象类来转发事件:

    class MovementFragment : Fragment(), MovementContract.View { var logic: BaseLogic<MovementEvent>? = null override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.fragment_movement, container, false) } override fun onStart() { super.onStart()//in this example we retrieve some arguments via the Navigation Library from Jetpack logic?.handleEvent( MovementEvent.OnStart( MovementFragmentArgs.fromBundle(arguments!!).movementId ) ) }}

    What About LiveData, Coroutines, RxJava…?

    那么LiveData,Coroutines,RxJava呢?

    If you think about it for a moment, you should realize than any of these tools will allow you to pass some kind of class/enum through a single method that can represent multiple different events or states. Some of these tools will also allow you to model events in a functional style, or you may also use Function references in Kotlin, Java 8+, or any language that supports that feature.

    如果您想一想,您应该意识到这些工具中的任何一种都将允许您通过一种可以表示多个不同事件或状态的方法来传递某种类/枚举。 其中一些工具还允许您以功能样式对事件进行建模,或者也可以在Kotlin,Java 8+或支持该功能的任何语言中使用功能引用。

    We will look at some samples for that in the next article.

    我们将在下一篇文章中查看一些示例。

    Happy coding, my cousin.

    我的表弟,编码愉快。

    社交媒体| 支持 (Social Media | Support)

    This article was written by Ryan Michael Kay. I am a self-taught programmer/engineer who creates educational content for on a wide variety of topics, on a wide variety of platforms. The best way to support me is to follow me on various platforms and join in with my developer community (we have hundreds of members!):

    本文由Ryan Michael Kay撰写。 我是一个自学成才的程序员/工程师,他在各种平台上为各种主题创建教育性内容。 支持我的最佳方法是在各种平台上关注我,并加入我的开发人员社区(我们有数百名成员!):

    Announcements:https://www.facebook.com/wiseassbloghttps://twitter.com/wiseAss301

    公告: https : //www.facebook.com/wiseassblog https://twitter.com/wiseAss301

    Tutorials & Courses:

    教程与课程:

    Free Tutorials, Live Q&A, Live Coding:https://www.youtube.com/channel/UCSwuCetC3YlO1Y7bqVW5GHg

    免费教程,实时问答,实时编码: https : //www.youtube.com/channel/UCSwuCetC3YlO1Y7bqVW5GHg

    Java Desktop Programming w/ JavaFX (Intermediate) — https://skl.sh/31pzCa1

    Java桌面编程瓦特/ JavaFX的(中级) - https://skl.sh/31pzCa1

    Complete Beginner Introduction To Java Programming (Beginner — Intermediate) — https://skl.sh/3fZbjos

    Java编程完整入门指南(初级—中级)— https://skl.sh/3fZbjos

    Android Apps With Kotlin & Android Studio (Beginner) — https://skl.sh/2ZU6ZT9

    具有Kotlin和Android Studio的Android应用程序(初学者)— https://skl.sh/2ZU6ZT9

    Material Design Android Programming w/ Kotlin (Intermediate) — https://skl.sh/2OrwrYZ

    带有Kotlin的Material Design Android编程(中级)— https://skl.sh/2OrwrYZ

    Connect:

    连接:

    Discord Group — https://discord.gg/2XVvCW

    不和谐集团- https://discord.gg/2XVvCW

    Slack Group — https://join.slack.com/t/wiseass/shared_invite/zt-3p7p67p1-ZEvEhlrznbksmvzS0Qtunw

    Slack组-https: //join.slack.com/t/wiseass/shared_invite/zt-3p7p67p1-ZEvEhlrznbksmvzS0Qtunw

    LinkedIn-https://www.linkedin.com/in/ryan-kay-808388114/

    领英-https ://www.linkedin.com/in/ryan-kay-808388114/

    翻译自: https://medium.com/swlh/simplify-your-ui-interactions-with-events-java-kotlin-any-language-5062c1b1e0e4

    kotlin和java语言

    相关资源:ElegantDialog:使用KotlinJava编写的用于Android的漂亮,可定制和交互式的对话框:smiling_face_with_heart-eyes:-源码
    Processed: 0.009, SQL: 9