代表经理有一个好的设计理念吗?

时间:2021-06-15 21:01:54

Many Android apps include a BaseActivity class of their own, which all Activities in the app extend. This is useful because it gives a central place to put functionality that's common across most/all activities. The main drawback of having a BaseActivity is you are then unable to use any of the Activity subclasses (ListActivity, etc.).

许多Android应用程序都包含自己的BaseActivity类,应用程序中的所有活动都会扩展。这很有用,因为它提供了一个集中的位置来放置大多数/所有活动中常见的功能。拥有BaseActivity的主要缺点是您无法使用任何Activity子类(ListActivity等)。

One alternative is to have an ActivityDelegate. This gives a central place for functionality while still allowing you to use Activity subclasses. It's also arguably more testable, since it uses composition instead of inheritance.

另一种方法是拥有一个ActivityDelegate。这为功能提供了一个中心位置,同时仍允许您使用Activity子类。它也可以说更可测试,因为它使用组合而不是继承。

Both of these solutions potentially lead to a lot of spaghetti code when the BaseActivity/ActivityDelegate gets too large and convoluted. A possible solution to this is to use the delegate pattern, but split the functionality into many different Delegates. This reduces spaghetti code in the Delegates, but then the Activities get more complicated - they're now trying to forward their on* methods to lots of different Delegates instead of just one.

当BaseActivity / ActivityDelegate变得过大且复杂时,这两种解决方案都可能导致大量的意大利面条代码。可能的解决方案是使用委托模式,但将功能拆分为许多不同的委托。这减少了代表中的意大利面条代码,但随后活动变得更加复杂 - 他们现在正试图将他们的on *方法转发给许多不同的代理而不是一个代理。

A possible solution to all of these problems is to use a Delegate Manager. The Delegate Manager keeps track of all the smaller Delegates in the app. Activities forward their on* methods to the Delegate Manager, which forwards them on to all of the individual Delegates. This accomplishes all of the following:

所有这些问题的可能解决方案是使用委托管理器。代理管理器跟踪应用程序中的所有较小代理。活动将他们的on *方法转发给代表管理器,代理管理器将它们转发给所有单独的代表。这实现了以下所有方面:

  • Dedupes code - all common functionality gets placed into one of the Delegates
  • 重复数据删除代码 - 所有常用功能都放入其中一个代理中

  • Allows use of Activity subclasses
  • 允许使用Activity子类

  • Simple code in all Activities - all on* methods are forwarded to just one class
  • 所有活动中的简单代码 - 所有on *方法都转发到一个类

  • Easily testable - it's simple to mock out everything around the Delegates and the Delegate Manager for unit tests
  • 易于测试 - 模拟代表和代理管理器周围的所有内容进行单元测试很简单

Has anyone tried using this pattern before? If so, how did it go?

有没有人尝试过使用这种模式?如果是这样,它是怎么回事?

1 个解决方案

#1


2  

As far as I understand, you're talking about one single DelegateManager object for the entire application. If this is the case, you can use registerActivityLifecycleCallbacks, see http://developer.android.com/reference/android/app/Application.html#registerActivityLifecycleCallbacks%28android.app.Application.ActivityLifecycleCallbacks%29

据我所知,您正在谈论整个应用程序的一个DelegateManager对象。如果是这种情况,您可以使用registerActivityLifecycleCallbacks,请参阅http://developer.android.com/reference/android/app/Application.html#registerActivityLifecycleCallbacks%28android.app.Application.ActivityLifecycleCallbacks%29

If you're on < API level 14 you need to take a look at: https://github.com/BoD/android-activitylifecyclecallbacks-compat.

如果您在 级别14,则需要查看:https:>

registerActivityLifecycleCallbacks lets you hook into the activities onXXX lifecycle methods.

registerActivityLifecycleCallbacks允许您挂钩有关XMLXX生命周期方法的活动。

Doing this certainly has all the benefits you described:

这样做肯定有你描述的所有好处:

  • decoupling being usable only when you actually need to repeat behavior which is kinda seldom for controller+view logic tied in together the way Activity works.
  • 解耦只有在你真正需要重复行为时才能使用,这种行为很少与控制器+视图逻辑很少结合在一起。

  • Removing inheritance is nice if you have activities you might reuse - but I've never had to do it before. But I guess a good use-case would be your home-cooked activity for handling settings or something like it that needs app-wide L&F & behavior.
  • 如果你有可能重复使用的活动,那么删除继承是很好的 - 但我以前从来没有这样做过。但我想一个好的用例将是你的家庭烹饪活动处理设置或类似需要应用程序范围的L&F和行为。

On the top of my head I can think of these downsides:

在我的头脑中,我可以想到这些缺点:

  • Using listeners all over the place can blur path of the application activity/call hierarchy and can make the code hard to understand. This holds true for all listener/dispatcher type of programming. It's a powerful tool, but handle it with care.
  • 在整个地方使用侦听器可以模糊应用程序活动/调用层次结构的路径,并且可以使代码难以理解。这适用于所有侦听器/调度程序类型的编程。它是一个强大的工具,但要小心处理它。

  • It can introduce a lot of (as you mention) boilerplate/spaghetti code if all you do is pass on to lifecycle listeners/delegates.
  • 如果您所做的只是传递给生命周期监听器/代理,它可以引入很多(如您所述)样板/意大利面条代码。

  • it is your responsibility to de-register yourself from the Application with Application.unregisterActivityLifecycleCallbacks. I don't think there's a good way around it,
  • 您有责任使用Application.unregisterActivityLifecycleCallbacks从Application中取消注册。我不认为有一个很好的方法,

Personally I haven't used this design-pattern much for lifecycles, but it might be worthwhile for some use-cases. For example:

就个人而言,我没有将这种设计模式用于生命周期,但对于某些用例来说可能是值得的。例如:

  • ApplicationLifecycleLogger: Every time you create/resume/pause... an activity, you logcat or something else making debugging lifecycles a tad bit easier.
  • ApplicationLifecycleLogger:每次创建/恢复/暂停...一个活动时,您都可以使用logcat或其他方式使调试生命周期更容易一些。

  • If for example someone goes into an activity he/she is not allowed to go into due to model state of some sort (e.g. a ringing alarm -> can't go into AlarmEditActivity), you could do finish() there.
  • 例如,如果有人进入活动,他/她不允许进入某种类型的模型状态(例如振铃警报 - >不能进入AlarmEditActivity),你可以在那里完成()。

  • Passing object state across activity boundaries without Parcelable:s and screen rotation changes. Usually this is implemented with a Map in Application or some static field somewhere. You can do this by letting the delegators hold state.
  • 在没有Parcelable:s和屏幕旋转更改的情况下跨越活动边界传递对象状态。通常,这是通过应用程序中的Map或某处的某个静态字段实现的。您可以通过让委托人保持状态来完成此操作。

Also, take a look at: Is there a design pattern to cut down on code duplication when subclassing Activities in Android?

另外,请看一下:在Android中进行子类化活动时,是否有一种设计模式可以减少代码重复?

I hope this was helpful =)

我希望这有用=)

#1


2  

As far as I understand, you're talking about one single DelegateManager object for the entire application. If this is the case, you can use registerActivityLifecycleCallbacks, see http://developer.android.com/reference/android/app/Application.html#registerActivityLifecycleCallbacks%28android.app.Application.ActivityLifecycleCallbacks%29

据我所知,您正在谈论整个应用程序的一个DelegateManager对象。如果是这种情况,您可以使用registerActivityLifecycleCallbacks,请参阅http://developer.android.com/reference/android/app/Application.html#registerActivityLifecycleCallbacks%28android.app.Application.ActivityLifecycleCallbacks%29

If you're on < API level 14 you need to take a look at: https://github.com/BoD/android-activitylifecyclecallbacks-compat.

如果您在 级别14,则需要查看:https:>

registerActivityLifecycleCallbacks lets you hook into the activities onXXX lifecycle methods.

registerActivityLifecycleCallbacks允许您挂钩有关XMLXX生命周期方法的活动。

Doing this certainly has all the benefits you described:

这样做肯定有你描述的所有好处:

  • decoupling being usable only when you actually need to repeat behavior which is kinda seldom for controller+view logic tied in together the way Activity works.
  • 解耦只有在你真正需要重复行为时才能使用,这种行为很少与控制器+视图逻辑很少结合在一起。

  • Removing inheritance is nice if you have activities you might reuse - but I've never had to do it before. But I guess a good use-case would be your home-cooked activity for handling settings or something like it that needs app-wide L&F & behavior.
  • 如果你有可能重复使用的活动,那么删除继承是很好的 - 但我以前从来没有这样做过。但我想一个好的用例将是你的家庭烹饪活动处理设置或类似需要应用程序范围的L&F和行为。

On the top of my head I can think of these downsides:

在我的头脑中,我可以想到这些缺点:

  • Using listeners all over the place can blur path of the application activity/call hierarchy and can make the code hard to understand. This holds true for all listener/dispatcher type of programming. It's a powerful tool, but handle it with care.
  • 在整个地方使用侦听器可以模糊应用程序活动/调用层次结构的路径,并且可以使代码难以理解。这适用于所有侦听器/调度程序类型的编程。它是一个强大的工具,但要小心处理它。

  • It can introduce a lot of (as you mention) boilerplate/spaghetti code if all you do is pass on to lifecycle listeners/delegates.
  • 如果您所做的只是传递给生命周期监听器/代理,它可以引入很多(如您所述)样板/意大利面条代码。

  • it is your responsibility to de-register yourself from the Application with Application.unregisterActivityLifecycleCallbacks. I don't think there's a good way around it,
  • 您有责任使用Application.unregisterActivityLifecycleCallbacks从Application中取消注册。我不认为有一个很好的方法,

Personally I haven't used this design-pattern much for lifecycles, but it might be worthwhile for some use-cases. For example:

就个人而言,我没有将这种设计模式用于生命周期,但对于某些用例来说可能是值得的。例如:

  • ApplicationLifecycleLogger: Every time you create/resume/pause... an activity, you logcat or something else making debugging lifecycles a tad bit easier.
  • ApplicationLifecycleLogger:每次创建/恢复/暂停...一个活动时,您都可以使用logcat或其他方式使调试生命周期更容易一些。

  • If for example someone goes into an activity he/she is not allowed to go into due to model state of some sort (e.g. a ringing alarm -> can't go into AlarmEditActivity), you could do finish() there.
  • 例如,如果有人进入活动,他/她不允许进入某种类型的模型状态(例如振铃警报 - >不能进入AlarmEditActivity),你可以在那里完成()。

  • Passing object state across activity boundaries without Parcelable:s and screen rotation changes. Usually this is implemented with a Map in Application or some static field somewhere. You can do this by letting the delegators hold state.
  • 在没有Parcelable:s和屏幕旋转更改的情况下跨越活动边界传递对象状态。通常,这是通过应用程序中的Map或某处的某个静态字段实现的。您可以通过让委托人保持状态来完成此操作。

Also, take a look at: Is there a design pattern to cut down on code duplication when subclassing Activities in Android?

另外,请看一下:在Android中进行子类化活动时,是否有一种设计模式可以减少代码重复?

I hope this was helpful =)

我希望这有用=)