MVP中模型中的需求上下文 [英] Need Context in Model in MVP

查看:74
本文介绍了MVP中模型中的需求上下文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在模型中使用活动上下文,同时在android中使用MVP来获取所有已安装应用程序的列表.什么是访问上下文的正确方法或遵循MVP模式时实现上下文的任何替代方法

I need to use the Context of activity in the model while using MVP in android to get the list of all the installed application.what is the correct way to access the context or any alternative to achieve the same while following the MVP pattern.

这是课程:

public class MainActivity extends BaseActivity
    implements MainView,View.OnClickListener {

private MainPresenter mPresenter;



private Button sendButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    init();
    createPresenter();


}

private void init(){

    sendButton= (Button) findViewById(R.id.button_send);
    sendButton.setOnClickListener(this);
}

private void createPresenter() {
    mPresenter=new MainPresenter();
    mPresenter.addView(this);
}





@Override
public void onClick(View view) {
    switch (view.getId()){
        case R.id.button_send:
            mPresenter.onSendButtonClick();
            break;
    }
}

@Override
public void openOptionsActivity() {
    Intent intent=new Intent(this,OptionsActivity.class);
    startActivity(intent);
}

}

公共类MainPresenter扩展了BasePresenter {

public class MainPresenter extends BasePresenter {

MainModel model;
public void onSendButtonClick(){

   model.getListOfAllApps();

}

@Override
public void addView(MainView view) {
    super.addView(view);
model=new MainModel();
}

}

public class MainModel {

public void getListOfAllApps(){
    final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
    mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
    final List pkgAppsList = getPackageManager().queryIntentActivities(mainIntent, 0);

}

}

getPackageManager().queryIntentActivities(mainIntent,0)中有问题.如何执行此操作,因为此处没有任何上下文.

having issue in getPackageManager().queryIntentActivities(mainIntent, 0) .how to do it as not having any context here.

推荐答案

我回答了类似的问题

I answered a similar question here which you may want to have a look at too. I'll give the breakdown of how I think you could solve this particular problem though.

使用Application类中的静态上下文

此方法可行,但我不喜欢它.它使测试更加困难,并将您的代码耦合在一起.

This method would work but I'm not fond of it. It makes testing harder and couples your code together.

public class App extends Application {

    private static Context context;

    public static Context getContext() {
        return context;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();
    }
}

然后在您的MainModel中:

Then in your MainModel:

public class MainModel {

    public List<String> getListOfAllApps(){

        final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
        mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        final List<ResolveInfo> pkgAppsList = App.getContext().getPackageManager().queryIntentActivities(mainIntent, 0);

        List<String> results = new ArrayList<>();
        for (ResolveInfo app : pkgAppsList) {
            results.add(app.resolvePackageName);
        }
        return results;
    }
}

现在我们已经解决了这个问题,让我们来看一些更好的选择.

Now we've got that out the way, let's look at some better options.

在活动中完成

因此,您的活动"将实现您的视图".它可能也在做一些Anrdoidy事情,例如onActivityResult.有一个参数可以将Android代码保留在Activity中,然后仅通过View界面进行访问:

So your Activity implements your View. It's probably doing a few Anrdoidy things too such as onActivityResult. There's an argument for keeping Android code in the Activity and just accessing it through the View interface:

public interface MainView {

    List<String> getListOfAllApps();
}

活动:

public class MainActivity extends BaseActivity implements MainView {

    //..

    @Override
    public List<String> getListOfAllApps(){

        final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
        mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        final List<ResolveInfo> pkgAppsList = getPackageManager().queryIntentActivities(mainIntent, 0);

        List<String> results = new ArrayList<>();
        for (ResolveInfo app : pkgAppsList) {
            results.add(app.resolvePackageName);
        }
        return results;
    }

    //..
}

主持人:

public class MainPresenter extends BasePresenter {

    public void onSendButtonClick(){

        view.getListOfAllApps();
    }
}

在单独的类中抽象详细信息

尽管最后一个选项没有违反MVP的规则,但感觉不是很正确,因为获取软件包列表并不是真的 View操作.我的首选方法是将Context的使用隐藏在接口/类的后面.

Whilst the last option doesn't break the rules of MVP it doesn't feel quite right as getting a list of packages isn't really a View operation. My preferred option is to hide the use of Context behind an interface/class.

创建一个类PackageModel(或任何您喜欢的名称):

Create a class PackageModel (or whatever name takes your fancy):

public class PackageModel {

    private Context context;

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

    public List<String> getListOfAllApps(){

        final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
        mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        final List<ResolveInfo> pkgAppsList = context.getPackageManager().queryIntentActivities(mainIntent, 0);

        List<String> results = new ArrayList<>();
        for (ResolveInfo app : pkgAppsList) {
            results.add(app.resolvePackageName);
        }
        return results;
    }
} 

现在,您的Presenter要求将此作为构造函数参数:

Now have your Presenter require this as a constructor parameter:

public class MainPresenter extends BasePresenter {

    private PackageModel packageModel;

    public MainPresenter(PackageModel packageModel) {
        this.packageModel = packageModel;
    }

    public void onSendButtonClick(){

        packageModel.getListOfAllApps();
    }
}

最后在您的活动中:

public class MainActivity extends BaseActivity implements MainView {

    private MainPresenter presenter;

    private void createPresenter() {

        PackageModel packageModel = new PackageModel(this);
        presenter = new MainPresenter(packageModel);
        presenter.addView(this);
    }
}

现在,Presenter隐藏了Context的使用,并且无需任何Android知识就可以继续使用.这称为构造函数注入.如果您使用的是依赖项注入框架,那么它可以为您构建所有依赖项.

Now the use of Context is hidden from the Presenter and it can carry on without any knowledge of Android. This is known as constructor injection. If you're using a dependency injection framework it can build all the dependencies for you.

如果您愿意,可以为PackageModel创建一个接口,但我认为这并不是真正必要的,因为像Mockito这样的模拟框架可以在不使用接口的情况下创建存根.

If you wanted to you could make an interface for PackageModel but I don't think it's really necessary as a mocking framework like Mockito can create a stub without using an interface.

这篇关于MVP中模型中的需求上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆