我最近写了我的第一个Android应用程序,大约有8,000-10,000行代码。在正常的设计模式中,一件不断妨碍我的事情是Android大量使用异步调用(打开对话框、活动等)。因此,我的代码很快开始看起来像"意大利面条",我最终开始讨厌看某些类。
是否有特定的设计模式或编程方法适用于这类系统,有人会推荐吗?有没有关于编写可管理的异步代码的建议?
我最近写了我的第一个Android应用程序,大约有8,000-10,000行代码。在正常的设计模式中,一件不断妨碍我的事情是Android大量使用异步调用(打开对话框、活动等)。因此,我的代码很快开始看起来像"意大利面条",我最终开始讨厌看某些类。
是否有特定的设计模式或编程方法适用于这类系统,有人会推荐吗?有没有关于编写可管理的异步代码的建议?
如果您不想用简单的 Intent.putExtra()
调用来搞乱您的代码,并为每个独特的 Activity
管理这些事情,那么您将需要在应用程序中使用全局变量。扩展 Application
并将您需要的数据存储在应用程序存活期间。要实际实现它,请使用此优秀的答案。这将使活动之间的依赖关系消失。例如,假设您需要一个 "用户名" 用于应用程序的生命周期 - 这是一个非常好的工具。无需使用低质的 Intent.putExtra()
调用。
在制作第一个 Android 应用程序时,一个常见的错误是通常只会开始编写 XML 视图。XML 文件将(毫不费力且非常快速地)达到很多行代码。在这里,您可以有一个解决方案,仅使用 style
属性即可实现特定的行为。例如,请考虑以下代码片段:
values/styles.xml:
<style name="TitleText">
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:textSize">18sp</item>
<item name="android:textColor">#000</item>
<item name="android:textStyle">bold</item>
</style>
layout/main.xml:
如果你有两个 TextView,并且它们的行为应该相同,那么让它们使用 TitleText 样式。示例代码:
<!--- ... -->
<TextView
android:id="@+id/textview_one"
style="@style/TitleText"
/>
<TextView
android:id="@+id/textview_two"
style="@style/TitleText"
/>
<!--- ... -->
简单且无需重复编码。如果您真的想进一步了解这个特定主题,请查看Layout Tricks: Creating Reusable UI Components。
这一点很简短,但我认为它很重要。开发人员可能会犯的另一个错误是跳过strings.xml,只是在代码中编写UI消息(和属性名称)(他将在其中需要)。为了使您的应用程序更易于维护,请在strings.xml文件中定义消息和属性。
当我写我的第一个应用程序时,我只是在需要它的地方编写(和复制)方法。结果?许多方法在各种活动之间具有相同的行为。我学到的是制作一个工具类。例如,假设您必须在所有活动中进行Web请求。在这种情况下,跳过在实际的Activity
中定义它们,并为其创建一个静态方法。示例代码:
public final class Tools {
private Tools() {
}
public static final void sendData(String url,
String user, String pass) {
// URLConnections, HttpClients, etc...
}
}
现在,您只需在需要向服务器发送数据的 Activity
中使用以下代码:Tools.sendData("www.www.www", "user", "pass");
然而,您明白了这个要点。在需要时使用这个"模式",它会让您避免破坏您的代码。
这可能是最有用的要点。仅仅定义 "用户需要与您的应用程序进行交互的地方"。比如说您有一个菜单(Menu)
,它的行为在几行代码中非常复杂,那么我们为什么要把菜单(Menu)
的计算放在同一个类中呢?每一个小项都会让您的活动(Activity)
类变成一堆令人痛苦的长代码——让您的代码看起来像 "意大利面条(Spaghetti)"。例如,与其写出以下代码:
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem item;
item = menu.findItem(R.id.menu_id_one);
if (aBooleanVariable) {
item.setEnabled(true);
} else {
item.setEnabled(false);
}
// More code...
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem i) {
// Code, calculations...
// ...
// ...
return super.onOptionsItemSelected(i);
}
重新设计为类似于这样的东西:
private MyCustomMenuInstance mMenuInstance;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mMenuInstance = new MyCustomMenuInstance();
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
mMenuInstance.onPrepareOptionsMenu(menu);
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem i) {
mMenuInstance.onOptionsItemSelected(i);
return super.onOptionsItemSelected(i);
}
例如,MyCustomMenuInstance
:public class MyCustomMenuInstance {
// Member fields..
public MyCustomMenuInstance() {
// Init stuff.
}
public void onPrepareOptionsMenu(Menu menu) {
// Do things..
// Maybe you want to modify a variable in the Activity
// class? Well, pass an instance as an argument and create
// a method for it in your Activity class.
}
public void onOptionsItemSelected(MenuItem i) {
// Do things..
// Maybe you want to modify a variable in the Activity
// class? Well, pass an instance as an argument and create
// a method for it in your Activity class.
}
}
你看到这里了吧。你可以将它应用于许多事情,例如 onClick
、onClickListener
、onCreateOptionsMenu
,清单很长。要了解更多的"最佳实践",你可以在Google的一些示例应用程序中查看这里。寻找他们如何以一种良好和正确的方式实现事物。
最后一个词;保持你的代码整洁,以逻辑方式命名你的变量和方法,特别是以正确的方式。始终要理解你在代码中的位置——这非常重要。
Util
而不是 Tool
。 - om-nom-nom我看到异步方法中最常见的错误之一就是在创建一个或多个线程的循环内使用静态变量,而没有考虑到该值可能在另一个线程中发生改变。避免使用静态变量!
正如 OceanBlue 指出的那样,可能不清楚的是 final static
变量不会带来任何危险,但是公共静态变量可以发生改变。这并不是静态本身的问题,而是这样的观念——它们将有一个值,然后发现该值已经改变。这可能很难找到问题所在。典型的例子是点击计数器或计时器的值,当可能存在多个视图被点击或多个计时器时。
希望你能收到比我更有经验的人的建议。祝你好运!
final static
变量不会出现这个问题。事实上,我更喜欢使用它们,因为它们不仅易于在需要时更改,而且有助于阅读清晰度。我将在我的答案中进一步澄清这一点。 - Aleadam使用模型视图控制器模式怎么样?
至少你需要在“模型”(对象或一组对象)中隔离所有状态及其逻辑管理,并在单独的类(可能是Activity类)中拥有与视图、监听器、回调等相关的所有内容。