在MVP模型中需要上下文

Har*_*rma 11 mvp android

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

这是课程:

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);
}
Run Code Online (Sandbox Code Playgroud)

}

公共类MainPresenter扩展BasePresenter {

MainModel model;
public void onSendButtonClick(){

   model.getListOfAllApps();

}

@Override
public void addView(MainView view) {
    super.addView(view);
model=new MainModel();
}
Run Code Online (Sandbox Code Playgroud)

}

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

}
Run Code Online (Sandbox Code Playgroud)

}

getPackageManager().queryIntentActivities(mainIntent,0).如何执行此操作,因为这里没有任何上下文.

Jah*_*old 23

在这里回答了一个类似的问题,你也可以看看.我会详细说明我认为你可以解决这个特殊问题.

使用Application类中的静态上下文

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

public class App extends Application {

    private static Context context;

    public static Context getContext() {
        return context;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

在活动中执行此操作

所以你的Activity实现了你的View.它可能也会做一些Anrdoidy事情,例如onActivityResult.将Android代码保存在Activity中并通过View界面访问它是有争议的:

public interface MainView {

    List<String> getListOfAllApps();
}
Run Code Online (Sandbox Code Playgroud)

活动:

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

    //..
}
Run Code Online (Sandbox Code Playgroud)

主持人:

public class MainPresenter extends BasePresenter {

    public void onSendButtonClick(){

        view.getListOfAllApps();
    }
}
Run Code Online (Sandbox Code Playgroud)

在单独的类中抽象细节

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

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

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;
    }
} 
Run Code Online (Sandbox Code Playgroud)

现在让Presenter将其作为构造函数参数:

public class MainPresenter extends BasePresenter {

    private PackageModel packageModel;

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

    public void onSendButtonClick(){

        packageModel.getListOfAllApps();
    }
}
Run Code Online (Sandbox Code Playgroud)

最后在你的活动中:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,Context的使用对于Presenter是隐藏的,它可以在不知道Android的情况下继续使用.这称为构造函数注入.如果您正在使用依赖注入框架,它可以为您构建所有依赖项.

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

  • 正如[此评论](http://stackoverflow.com/questions/37137624/how-to-use-shared-preferences-in-mvp-without-dagger-and-not-causing-presenter-to#comment61849985_37138822)所说,它只是隐藏了依赖,这更糟糕.[答案](http://stackoverflow.com/a/372​​16407/1276636)在同一个线程上非常好,因为它使依赖关系非常清晰.我发现[此视频](https://www.youtube.com/watch?v=-FRm3VPhseI&index=2&list=PL693EFD059797C21E)非常适合单身人士和隐藏的依赖关系. (3认同)

归档时间:

查看次数:

12751 次

最近记录:

9 年,5 月 前