Android MVP,获取剪贴板数据时出现同样的旧上下文问题?

Android MVP, same old context problem when getting clipboard data?

所以我需要在演示者中获取剪贴板数据。这意味着我需要 context。不幸的是,如果它是唯一的标准方法,我对依赖注入一无所知。 我研究了一些解决方案,但它们被认为是错误的解决方案。

public class MainActivityPresenter implements MainActivityInterfaces.MainToPresenter {

MainActivityInterfaces.PresenterToMain main;


public MainActivityPresenter (MainActivityInterfaces.PresenterToMain main) {
    this.main = main;
}


@Override
public void processUrl() {
    String url = Utils.getClipboardData(context);
    if (url.isEmpty()) {

    } else {

    }
}


}

这是Utils中的方法class

public static String getClipboardData (Context context) {
    if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) {
        android.text.ClipboardManager cm = (android.text.ClipboardManager) context.getSystemService(CLIPBOARD_SERVICE);
        String result = cm.getText().toString();
        return result==null?"":result;
    } else {
        ClipboardManager cm = (ClipboardManager) context.getSystemService(CLIPBOARD_SERVICE);
        ClipData.Item item = cm.getPrimaryClip().getItemAt(0);
        if (item != null)
            return item.getText().toString();
        else
            return "";
    }
}

正确的方式,演示者不应该知道任何特定的 Android 元素,ClipboardManagerContext(即:它应该是纯 Java)。剪贴板逻辑应该在 View 中进行,并将它需要的任何内容返回给 Presenter

丑陋的方式,如果要继续这样设计,processUrl应该拿Context,想必这个方法是从视图中调用的吧?这就是可以提供上下文的地方。

@Override
public void processUrl(Context context) {
    String url = Utils.getClipboardData(context);
    if (url.isEmpty()) {

    } else {

    }
}

在视图中:

presenter.processUrl(getApplicationContext());

另一种解决方案是向演示者请求上下文:

@Override
public void processUrl() {
    final Context context = view.getContext();
    String url = Utils.getClipboardData(context);
    if (url.isEmpty()) {

    } else {

    }
}

//In the view
void Context getContext() {
    return getApplicationContext();
}

在 Presenter 中使用上下文不是一个好主意。

What if I need the Context?

Well, get rid of it. In cases like this, you should ask yourself why you need the context. You may need the context to access shared preferences or resources, for example. But you shouldn’t do that in the presenter: you should access to resources in the view and to preferences in the model. These are just two simple examples, but I can bet that the most of the times it is just a problem of wrong responsibilities.

您可以在视图的构造函数中传递 url。

public class MainActivityPresenter implements MainActivityInterfaces.MainToPresenter {

MainActivityInterfaces.PresenterToMain main;
private String mUrl;

public MainActivityPresenter (MainActivityInterfaces.PresenterToMain main, String mUrl) {
    this.main = main;
    this.mUrl = mUrl;
}

@Override
public void processUrl() {
    if (mUrl.isEmpty()) {

    } else {

    }
}
interface SomeView {
    void onUrlProcessed();
}
}

在您的 MainActivity 中:

class MainActivity {

String url = Utils.getClipboardData(getContext());
}

您可以在这里参考其他答案。

Android MVP: safe use Context in Presenter

在 MVP 中,当 View 将事件传播 到 Presenter 时,某些信息被发送到 Presenter 是很常见的.在您的情况下,按如下方式重命名您的方法是很合乎逻辑的:

@Override
public void processUrl(String url) {
  if (url.isEmpty()) {

  } else {

  }
}

这样,View 将负责随事件一起传播信息。而且你还在 Presenter 中保留对 ViewAndroid 事物)的特殊性的无知,这在 MVP 中非常重要模式。

祝你好运!

我知道这对您的问题没有帮助。但除了 MVP 之外,MVVM 是一种更健壮和更简洁的模式,它不需要像 MVP 那样多的样板代码,所以如果你仍处于开始项目和决定架构的阶段,我可以,作为专业 Android 开发人员,只推荐 MVVM。由于 LiveData 存在于 ViewModel 中,MVVM 还会进行状态保存,因此您不必通过保存的实例包痛苦地向演示者添加功能。

如果您需要 DI 以便将上下文注入演示者(这是不可取的,理想情况下上下文不应进入演示者,但有时会发生这种情况,因为创建执行上下文所需工作的实体更加困难在演示者中),并且您是 DI 的新手并且没有经验,那么对于 Java,您需要使用 Dagger 2,它的学习曲线很陡。切换到 Kotlin 然后使用 Koin 可能比学习 Dagger 2 更容易,但如果您喜欢它,请尝试一下。无论如何,在专业项目中都需要 DI。

如果您不想使用 DI 将上下文传递给演示者,则将其传递给构造函数。我想 Activity 或 Fragment 是您初始化演示者(创建它的新实例)以及将 'view' 概念传递给演示者的地方。如果您需要演示者中的上下文(同样,这不是最好的做法,但没关系,我理解您是模式的新手),然后只需将其传递给构造函数并在演示者中进行设置。