简体   繁体   English

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

[英]Android MVP - passing string resources from the presenter to the view

I've recently started developing an Android app with a model–view–presenter architecture. 我最近开始开发具有模型-视图-演示者架构的Android应用。 One issue that keeps coming up that I haven't been able to find a good solution for is passing strings from the presenter to be displayed in the view. 我一直无法找到一个好的解决方案的一个不断出现的问题是传递来自演示者的字符串以显示在视图中。

I am trying to keep Android system dependencies out of the presenter layer to make unit testing easier. 我试图将Android系统依赖项排除在presenter层之外,以简化单元测试。 This is simple when providing a string that comes from a server or some other external source. 当提供来自服务器或其他外部来源的字符串时,这很简单。 When I need to display a simple error message that is always the same, I can just have a method like showWhateverError() , where the view already knows which string resource to use and can handle loading the resource itself. 当我需要显示一条总是相同的简单错误消息时,我可以使用showWhateverError()类的方法,其中视图已经知道要使用哪个字符串资源,并且可以处理资源本身的加载。 And when I have business logic that determines which string resource to provide the view, I can just reference the string resource ID in the presenter (although that feels wrong too). 当我有确定要提供视图的字符串资源的业务逻辑时,我可以在演示者中引用字符串资源ID(尽管这也感觉不对)。

The case that I haven't come up with a good solution for is when I need to display a string that sometimes comes from the server and is sometimes a string resource, based on some business logic. 我尚未提出好的解决方案的情况是,当我需要基于某些业务逻辑显示有时来自服务器且有时是字符串资源的字符串时。 Any ideas would be helpful! 任何想法都会有所帮助!

For these situations I have additional helper class which I call a Formatter . 对于这些情况,我还有一个附加的帮助程序类,称为“ Formatter I pass the current state from my Presenter to the View which then asks the Formatter for the appropriate strings based on that state. 我将当前状态从Presenter传递给View ,然后ViewFormatter询问基于该状态的适当字符串。 I think a small example will help: 我认为一个小例子会有所帮助:

You have an object which represents the data you wish to set on the View. 您有一个对象,它表示您希望在视图上设置的数据。 Let's call it State for now: 现在将其称为“ 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;
    }
}

In you Presenter you would create this based on whatever logic you need and pass it to the View : Presenter您将根据需要的逻辑来创建它,并将其传递给View

public class MessagePresenter {

    private void setMessage() {

        // logic here

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

Then in your Activity/Fragment/ViewGroup you'd have something along the lines of: 然后,在您的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);
    }
}

As you can see the view asks the Formatter for the String to display in the TextView. 如您所见,该视图要求Formatter提供要在TextView中显示的字符串。 The Formatter would look something like this: 格式化程序如下所示:

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);
    }
}

It takes a Context as a constructor param and, yes it does have a little bit of logic in it. 它把Context作为构造函数的参数,是的,它确实有一点逻辑。 However the heavy lifting logic remains in the Presenter . 但是,沉重的逻辑仍保留在Presenter Most of the time it should just be a simple boolean check. 大多数时候,它应该只是一个简单的布尔检查。

The real power of using this method comes into play when you make a Formatter interface and then use your Presenter to decide which Formatter to instantiate. 当您创建一个Formatter接口,然后使用Presenter来确定要实例化哪个 Formatter时,使用此方法的真正作用就发挥了作用。 As an example you can then create a HoliidayMessageFormatter and a DefaultMessageFormatter which would allow you to give you app a different theme based on a small logic check in the Presenter . 作为示例,您可以创建HoliidayMessageFormatterDefaultMessageFormatter ,这将允许您基于Presenter的小逻辑检查为您的应用程序提供不同的主题。

The error message visualisation must be handled using View! 错误消息的可视化必须使用View处理!

Your presenter have to call the related error method, for instance invalidEmail(), and the view have to decide how to interact with user and use UI elements to show the error. 演示者必须调用相关的错误方法,例如invalidEmail(),并且视图必须决定如何与用户交互以及使用UI元素显示错误。

In some implementations you may want to show an animation instead of a message! 在某些实现中,您可能希望显示动画而不是消息! therefore sending the message from down layers to view is not right. 因此从下层发送消息以进行查看是不正确的。

Here is a sample repo which can help you with learning more about MVP, Dagger, Testing and other concepts: 这是一个示例仓库,可以帮助您了解有关MVP,Dagger,测试和其他概念的更多信息:

http://github.com/mmirhoseini/marvel http://github.com/mmirhoseini/marvel

I hope it help :) 希望对您有所帮助:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM