简体   繁体   English

Android MVP,获取剪贴板数据时是否存在相同的旧上下文问题?

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

So I need to get clipboard data in presenter. 所以我需要在演示者中获取剪贴板数据。 This means I need context . 这意味着我需要context Unfortunately I don't have any knowledge of dependency injection if it is the only standard way. 不幸的是,如果这是唯一的标准方法,那么我对依赖注入一无所知。 I studied some solutions but they are stated as faulty solutions. 我研究了一些解决方案,但它们被认为是错误的解决方案。

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 {

    }
}


}

And this is the method in Utils class 这是Utils类中的方法

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

The right way , The presenter shouldn't know about any specific Android element, ClipboardManager or Context (ie: it should be pure Java). 正确的方法是 ,演示者不应该知道任何特定的Android元素, ClipboardManagerContext (即:它应该是纯Java)。 The clipboard logic should be taking place within the View and returning whatever it needs to the Presenter . 剪贴板逻辑应在View内进行,并将所需的内容返回给Presenter

The ugly way , if you want to continue with this design, processUrl should take Context, presumably this method is being called from the view? 丑陋的方式 ,如果您想继续进行此设计, processUrl应该采用Context,大概是从视图中调用此方法吗? So that is where context can be provided. 这样便可以提供上下文。

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

    } else {

    }
}

In the view: 在视图中:

presenter.processUrl(getApplicationContext());

Another solution is to ask for context from the presenter to the view: 另一个解决方案是从演示者到视图请求上下文:

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

Using context in Presenter is not a good idea. 在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. 这只是两个简单的示例,但是我敢打赌,在大多数情况下,这只是责任不当的问题。

You can pass url in constructor from View. 您可以通过View在构造函数中传递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();
}
}

In your MainActivity: 在您的MainActivity中:

class MainActivity {

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

You can refer other answers here . 您可以在此处参考其他答案。

Does the presenter having knowledge of the Activity / Context a bad idea in the MVP pattern? 演示者了解活动/上下文对MVP模式是一个坏主意吗?

Android MVP: safe use Context in Presenter Android MVP:Presenter中的安全使用上下文

At MVP, when the View propagates an event to the Presenter, it is very common for certain information to be sent to the Presenter . 在MVP上,当View将事件传播到Presenter时,通常会将某些信息发送到Presenter In your case, it would be quite logical to rename your method as follows: 在您的情况下,按以下方式重命名方法是很合逻辑的:

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

  } else {

  }
}

In this way, the View will be in charge of propagating the information along with the event. 这样,视图将负责与事件一起传播信息。 And you also keep in the Presenter the ignorance about the peculiarities of the View ( Android things ), something very important in the MVP pattern. 而且,您还可以在Presenter中保持对ViewAndroid事物特性的无知 ,这在MVP模式中非常重要。

Good luck! 祝好运!

I know this won't help your question. 我知道这对您的问题无济于事。 But aside from MVP, MVVM is much robust and cleaner pattern that doesn't require as much boilerplate code as MVP does, so if you are still in a phase where you are starting a project and deciding or an architecture, I can, as a professional Android developer, only recommend MVVM. 但是,除了MVP之外,MVVM是一种更健壮,更简洁的模式,不需要像MVP那样需要大量的样板代码,因此,如果您仍处于开始项目,决定或架构的阶段,我可以专业的Android开发人员,仅推荐MVVM。 MVVM also does the state saves due to LiveData living inside ViewModels so you don't have to painfully add the ability to the presenter via saved instance bundles. 由于LiveData驻留在ViewModels中,因此MVVM也会保存状态,因此您不必通过保存的实例捆绑包将功能轻松地添加到演示者中。

If you need DI in order to inject the context into the presenter (which isn't desirable, context shouldn't get into presenters ideally but sometimes it happens as it is harder to create entities that do the context required job in the presenter), and you are new and unexperienced in DI, then with Java you need to go with Dagger 2, which has a steep learning curve. 如果您需要DI以便将上下文注入到演示者中(这是不希望的,则上下文不应理想地进入演示者,但有时会发生,因为创建在演示者中完成上下文所需工作的实体比较困难),并且您是新手,并且对DI没有经验,那么使用Java时,您需要使用Dagger 2,它具有陡峭的学习曲线。 Switching to Kotlin and then using Koin would be perhaps easier than learning Dagger 2, but if you are into it, try it. 切换到Kotlin然后再使用Koin可能比学习Dagger 2容易,但是如果您愿意,可以尝试一下。 In any way it is a required to have DI in a professional projects. 无论如何,在专业项目中都需要具有DI。

If you don't want to use DI in order to pass the context into the presenter, then pass it into the constructor. 如果您不想使用DI来将上下文传递给演示者,则将其传递给构造函数。 I guess the Activity or Fragment is where you initialise your presenter (creating a new instance of it) and where you pass the 'view' concept into the presenter. 我猜想Activity或Fragment是初始化演示者(创建它的新实例)的地方,也是将“视图”概念传递给演示者的地方。 If you need context in the presenter (again, not the best thing to do but ok, you are a new into patterns I understand), then just pass it into the constructor and set it in the presenter. 如果您需要演示者中的上下文(同样,不是最好的事情,但是可以,您是我了解的新模式),只需将其传递到构造函数中并在演示者中进行设置即可。

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

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