【问题标题】:android MVP - How should the network layer be called , from model?android MVP - 应该如何从模型中调用网络层?
【发布时间】:2017-04-26 03:14:11
【问题描述】:

在 MVP android 中,我相信网络层(改造、凌空等)不应该是模型的一部分。但是我需要一个关于如何构建模型的可靠示例。模型应该是网络层在 api 调用完成时简单创建的单例吗?

让我们来看看我的一个活动的演示者:

    public class MainActivityPresenter implements IMainPresenterContract, Callback {

    IMainActivityViewContract view;//todo set up a weak reference to View to avoid leakage
    NewsService interactor;

    public MainActivityPresenter(IMainActivityViewContract view, NewsService interactor) {
        this.view = view;
        this.interactor = interactor;
    }


    public void loadResource() {
        interactor.loadResource();
    }


    public void onRequestComplete(final NewsEntities newsEntities) {

        view.dataSetUpdated(newsEntities.getResults());
    }

    @Override
    public void onResult(final NewsEntities newsEntities) {
        onRequestComplete(newsEntities);
    }

    public void goToDetailsActivity(Result result) {
        view.goToDetailsActivity(result);
    }
}

所以我的问题是关于我传递给构造函数的 NewsService 交互器参数。我假设这应该是模型数据而不是网络服务。但它应该是什么样子呢?目前我的看起来像这样:

    public class NewsService implements INewsServiceContract {

    private Gson gson;
    private Callback mCallback;


    public NewsService() {
        configureGson();
    }

    private static String readStream(InputStream in) {
        StringBuilder sb = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {

            String nextLine;
            while ((nextLine = reader.readLine()) != null) {
                sb.append(nextLine);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    public void setCallBack(Callback cb) {
        mCallback = cb; // or we can set up event bus
    }

    private void configureGson() {


        GsonBuilder builder = new GsonBuilder();
        builder.excludeFieldsWithoutExposeAnnotation();
        gson = builder.create();
    }

    @Override
    public void loadResource() {
//Todo could use a loader instead help with the config change or a headless fragment
        new AsyncTask<String, String, String>() {
            @Override
            protected String doInBackground(String... params) {
                String readStream = "";
                HttpURLConnection con = null;
                try {
                    URL url = new URL("https://api.myjson.com/bins/nl6jh");
                    con = (HttpURLConnection) url.openConnection();
                    readStream = readStream(con.getInputStream());
                } catch (Exception e) {
                    e.printStackTrace();
                }

                finally {
                    if(con!=null)
                    con.disconnect();
                }
                return readStream;
            }

            @Override
            protected void onPostExecute(String result) {
                super.onPostExecute(result);
                NewsService.this.onRequestComplete(result);


            }
        }.execute();
    }

    private void onRequestComplete(String data) {

        data = data.replaceAll("\"multimedia\":\"\"", "\"multimedia\":[]");
        news.hotels.com.sample.Model.NewsEntities newsEntities = gson.fromJson(data, NewsEntities.class);
        mCallback.onResult(newsEntities);
    }
}

如您所见,在这种情况下,NewsService 正在执行网络调用。我想我不应该把它传递给演示者。但是如何构建模型呢?谁调用 NewsService?

更新:这个问题是很久以前的问题了,请大家使用干净的架构方法,让你的演示者对网络层一无所知。

【问题讨论】:

    标签: android mvp


    【解决方案1】:

    网络调用需要在模型层,并且应该由演示者触发。但它的模型层决定在哪里设置数据并将其隐藏在 Presenter 层中。

    我自己使用模型层中的交互器类来执行此操作,演示者将使用此交互器获取数据,交互器将从数据库或服务器获取有关情况的数据。

    在我的 repo 中查看这个示例项目:

    https://gitlab.com/amirziarati/Echarge

    我用 Dagger 做 DI 可能会让你感到困惑。看看包装以及我如何在层之间分离关注点。

    更新:我使用演示者同步来自服务器和数据库的数据,这是错误的。演示者应该对此过程一无所知。我当时没有意识到这个问题。

    【讨论】:

    • 我无法查看您的项目。我成功注册了一个 gitlab 帐户,但我看不到任何源代码。它是一个空项目。
    • 检查一下
    • 我公开了 ;) 再看看
    • operatorPresenter 没有单元测试,所以我可以看到你是如何测试这个 Presenter 的。构造函数有这么多依赖,你打算全部模拟出来吗?因此 getOperator 方法是您在 create 方法上的活动中调用的。此方法执行 API 调用。所以你让演示者调用 api 调用并更新数据库。并且 OperatorPresenter 接受一个 DBHelper 。所以在这种情况下,网络层调用不是模型的一部分。你也把它分开了,但是演示者调用它。还有你为什么把网络层放在一个 lib 文件夹中?
    • 我将 Presenter 和 Model 层放在纯 java 库中的原因是我始终记得我不能在其中使用 Android 相关的东西,实际上我不能因为它阻止我进行单元测试。您可以通过模拟交互器对 api 调用进行单元测试。一切都可以进行单元测试。告诉我什么是不可能进行单元测试的,我会为此编写单元测试;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-07
    • 2011-05-09
    • 1970-01-01
    • 2017-04-10
    • 1970-01-01
    • 2016-08-22
    • 1970-01-01
    相关资源
    最近更新 更多