Android 模式:一个 Spinner,其中每个项目都会启动不同的 Activity

发布于 2024-11-15 01:22:39 字数 601 浏览 3 评论 0 原文

我正在尝试构建一个复杂的表单,其中几乎所有元素都是可选的。它以一个字段和一个“添加元素”按钮开始。单击“添加”时,表单会显示一个 Spinner,其中包含您可以添加到表单的元素类型(位置、照片、详细说明、除“现在”之外的时间戳等)。当您选择一个项目时,它将启动一个Activity,并且每个项目都有一个不同关联的Activity

此外,每个选择都会有几位数据,最好以某种方式与 Activity 一起存储:

  • 图标和 Spinner 中显示的
  • 名称用于将数据存储在数据库中的密钥(以及传递给网络服务)
  • 如何在原始表单上显示结果的布局(即照片的缩略图、位置的纬度/经度等)

我正在考虑一组全部扩展抽象的类FormElement 类,并且将为上述每个额外数据片段提供静态元素。 (此解决方案的另一个障碍是静态上下文中的资源有多么痛苦。)

如何使其尽可能干净且可维护?我真的不喜欢编辑五个不同的文件来向此表单添加新类型的元素。 (主要是因为我可以保证我会错过一个并花几个小时寻找无缺陷的东西。)

I'm trying to build a complex form where almost all of the elements are optional. It starts with just a single field and an "add element" button. When you click add, the form shows a Spinner of the types of elements you can add to the form (location, photo, detailed note, timestamp other than "now", etc). When you select an item, it will launch an Activity, and each item has a different associated Activity.

In addition, each choice will have several bits of data, which it would be nice to store "with" the Activity somehow:

  • An icon and the displayed name in the Spinner
  • A key for storing the data in the db (as well as passing to a webservice)
  • A layout for how to display the result on the original form (i.e. a thumbnail for the photo, the lat/lon for the location, etc)

I was considering a set of classes that all extend an abstract FormElement class, and would have static elements for each of the above extra pieces of data. (An additional bump for this solution is how much of a pain Resources are in a static context.)

How can I make this as clean and maintainable as possible? I'd really not enjoy editing five different files to add a new type of element to this form. (Mostly because I can guarantee I'll miss one and spend hours chasing down unbugs.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

木落 2024-11-22 01:22:39

一些提示...

  1. 单元测试将防止“无错误”:)

  2. 当每个Activity从用户那里获取了它需要的信息时,调用Activity#setResult() ,其中 Intent 包含您的每个-类型 数据。 Intent支持所有Bundle方法,因此您可以根据需要设置不同类型的数据。

  3. 要支持#2,请确保使用 Activity#startActivityForResult(Intent,int) 启动它,并在 Activity#onActivityResult(int,Intent) 中侦听结果

  4. 我可能会维护与 SpinnerAdapter 一起使用的可用“元素”类型列表(例如,ArrayList>,并在 Adapter 的 getView()< 中调用静态方法,如 .getDisplayName().getActivityClass() 等/code> 方法,以确定要显示的内容以及要启动的 Activity。

    这样,您的列表实际上将包含类似 { MyPhotoElement.class, MyTextElement.class, MyDateElement.class, ...}) 的内容。

  5. 将每个元素添加到表单后,将其添加到 ArrayList 中,该元素将用于支持 ListView 的另一个适配器。该适配器将调度自定义视图布局的膨胀,以及创建 ViewHolder,基于对象的类型 - 这将要求每个不同的 AbstractFormElement 都有自己的“视图”类型”,根据适配器。请参阅 BaseAdapter#getItemViewType(int) 和相关内容getViewTypeCount()

    值得注意的是,如果一个不能转换为另一个,则这些将需要不同的视图类型...例如,如果您有两个“元素”,只需要显示一串列表中的文本,它们都可以共享“纯文本”视图类型。同样,仅显示照片或可以轻松地将一个元素转换为另一个元素(例如,带标题的图标与不带标题的照片缩略图)的两个元素可以共享单个“图像加标题”视图类型。

考虑到上述内容,您实际上最终必须修改不同的文件来添加新类型(好吧,我想从技术上讲,您可以将它们全部放在一个文件中,作为内部类,但确实没有很好的理由这样做) ,但是如果您正确地完成了接口 API,并遵循良好的 OO 实践,并实现了良好的单元测试,您将大大减少查找错误所需的工作量 - 仅仅因为大多数事情都涉及添加新的如果你这样做,类型实际上会强制编译器错误错误地。除此之外,一个适当的单元测试套件将能够以编程方式添加所有可能的类型,并确保所有内容都正确显示,并且您应该有一个非常简化的流程以方便扩展:)

这听起来像是很多工作,并且起初它可能看起来乏味且冗长......但最终结果实际上更易于维护,特别是如果您的元素类型列表相当广泛。

A few tips...

  1. Unit tests will prevent "unbugs" :)

  2. When each Activity has obtained the information it needs from the user, call Activity#setResult() with an Intent that contains your per-type data. Intent supports all the Bundle methods, so you can set different types of data as needed.

  3. To support #2, make sure you're using Activity#startActivityForResult(Intent,int) to launch it, and listen for the result in Activity#onActivityResult(int,Intent)

  4. I would probably maintain the list of available "element" types for use with the SpinnerAdapter (e.g., ArrayList<Class<? extends AbstractFormElement>>, and invoke static methods like .getDisplayName(), .getActivityClass(), etc, in the Adapter's getView() method, in order to determine what to display and what Activity to launch.

    In this way, your list would actually contain things like { MyPhotoElement.class, MyTextElement.class, MyDateElement.class, ...}).

  5. As each element is added to the form, add it to an ArrayList<AbstractFormElement>, which will be used to back another Adapter for a ListView. That adapter will dispatch the inflation of a custom view layout, as well as the creation of a ViewHolder, based on what type of object it is -- that will require that each distinct AbstractFormElement will have its own "view type", according to the Adapter. See BaseAdapter#getItemViewType(int) and related getViewTypeCount().

    It's worth noting that these will need distinct view types only if one cannot be converted to the other... For example, if you have two "Elements" that only need to display a string of text in the list, those can both share a "text-only" view type. Likewise, two elements that only display a photo, or can easily convert one to the other (e.g., an icon with a caption, vs a photo thumbnail with no caption), can share a single "image-plus-caption" view type.

With the above in mind, you actually would end up having to modify different files to add a new type (well, I guess technically you could have them all in one file, as inner classes, but there's really no good argument for doing that), but if you've done your interface API correctly, and follow good OO practices, and implement good unit tests, you'll considerably reduce the amount of effort required to find bugs -- simply because most of the things involved in adding a new type would actually force a compiler error if you do it incorrectly. Add to that the fact that a proper unit test suite will be able to programmatically add all possible types, and ensure that everything displays properly, and you should have a pretty streamlined process for easy extensibility :)

It sounds like a lot of work, and it might seem tedious and verbose at first... But the end result is actually much more maintainable, especially if your list of element types is going to be fairly extensive.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文