Android MVP - 将字符串资源从演示者传递到视图

Android MVP - passing string resources from the presenter to the view

我最近开始开发一个 Android 具有模型-视图-呈现器架构的应用程序。一个不断出现但我一直无法找到好的解决方案的问题是从演示者传递字符串以显示在视图中。

我试图将 Android 系统依赖项排除在表示层之外,以使单元测试更容易。当提供来自服务器或其他一些外部源的字符串时,这很简单。当我需要显示一条始终相同的简单错误消息时,我可以使用类似 showWhateverError() 的方法,其中视图已经知道要使用哪个字符串资源并且可以处理加载资源本身。当我有确定哪个字符串资源提供视图的业务逻辑时,我可以在演示者中引用字符串资源 ID(尽管这也感觉不对)。

我还没有想出一个好的解决方案的情况是,当我需要显示一个字符串时,该字符串有时来自服务器,有时是一个字符串资源,基于一些业务逻辑。任何想法都会有所帮助!

必须使用 View 处理错误消息可视化!

您的演示者必须调用相关的错误方法,例如 invalidEmail(),视图必须决定如何与用户交互并使用 UI 元素来显示错误。

在某些实现中,您可能希望显示动画而不是消息!因此从下层发送消息给视图是不对的。

这里有一个示例存储库,可以帮助您更多地了解 MVP、Dagger、测试和其他概念:

http://github.com/mmirhoseini/marvel

希望对您有所帮助:)

对于这些情况,我有额外的助手 class,我称之为 Formatter。我将当前状态从我的 Presenter 传递到 View,然后 View 根据该状态向 Formatter 询问适当的字符串。我认为一个小例子会有所帮助:

您有一个对象代表您希望在视图上设置的数据。我们暂时称它为 State

public class State {

    private final boolean isServerString;
    private final String serverString;

    public State(boolean isServerString, String serverString) {
        this.isServerString = isServerString;
        this.serverString = serverString;
    }

    public boolean isServerString() {
        return isServerString;
    }

    public String getServerString() {
        return serverString;
    }
}

在你 Presenter 中,你将根据你需要的任何逻辑创建它并将它传递给 View:

public class MessagePresenter {

    private void setMessage() {

        // logic here

        State state = new State(true, "Hello from the server");
        view().setMessage(state);
    }
}

然后在您的 Activity/Fragment/ViewGroup 中,您会得到类似以下内容的内容:

public class MyActivity extends Activity implements MessageView {

    private MessageFormatter formatter;
    private TextView messageTextView;

    @Override
    public setMessage(State state) {

        String message = formatter.getMessage(state);
        messageTextView.setText(message);
    }
}

如您所见,视图要求 Formatter 将字符串显示在 TextView 中。格式化程序看起来像这样:

public class MessageFormatter {

    private Context context;

    public MessageFormatter(Context context) {
        this.context = context;
    }

    public String getMessage(State state) {

        return state.isServerString()
                ? state.getServerString()
                : context.getString(R.string.default_message);
    }
}

它需要一个 Context 作为构造函数参数,是的,它确实有一点逻辑。然而,繁重的逻辑仍在 Presenter 中。大多数时候它应该只是一个简单的布尔检查。

当您创建一个 Formatter 界面,然后使用您的 Presenter 来决定 哪个 Formatter 来实例化。例如,您可以创建一个 HoliidayMessageFormatter 和一个 DefaultMessageFormatter,这将允许您根据 Presenter.

中的小逻辑检查为您的应用程序提供不同的主题