I am new to Android MVP Architecture
. As far as I have researched the Presenter
should be kept free from any android things like for example: Don't use getActivity
or Context
in the Presenters. I have written the following code where a BasePresenter
is the parent class of all the Presenter
classes that I will be using.The BaseView
interface is the parent interface of all View classes and BaseActivity
class is the parent class of all Activity
classes. I have more than one activity and it is required to show Toast
messages in all of my activity. So I have written the following code as follows. I am not very sure whether using the getactivity
from the presenter class is a good practice or not. If it is not then can anyone suggest any better way to do it?
BasePresenter class
public class BasePresenter<V extends BaseView> {
private V mView;
private Context mContext;
public void attachView(V view) {
mView = view;
mContext=mView.getActivity();
}
public void showToast(String msg) {
Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();
}
private Context getContext() {
return mContext;
}
public void detachView() {
mView = null;
}
}
BaseView class
public interface BaseView {
AppCompatActivity getActivity();
}
BaseActivity class
public class BaseActivity extends AppCompatActivity {
public AppCompatActivity getActivity() {
return this;
}
}
MainActivity class
public class MainActivity extends BaseActivity implements MainView {
MainPresenter basePresenter;
@Override
protected void onStart() {
super.onStart();
basePresenter = new MainPresenter();
basePresenter.attachView(this);
}
// some more codes here
switch (item.getItemId()) {
case R.id.about:
basePresenter.showToast("About is Clicked");
break;
case R.id.cart:
basePresenter.showToast("Cart is Clicked");
break;
case R.id.favs:
basePresenter.showToast("Favs is Clicked");
break;
case R.id.home:
basePresenter.showToast("Home is Clicked");
break;
}
}
It is not a good idea. You Presenter (base or otherwise) should not know about Context, Activity, Toast or anything else Android based.
View
Presenter
.Presenter
View
what to do.So for your example of clicking Buttons and showing Toasts you would need a setup something like:
This is how your Presenter will talk to your View. It will be implemented by the Activity.
public interface MainView {
void showToast(String message);
}
BasePresenter has almost no tasks at all. Simply there to bind the View interface. Note the method names in the MainPresenter are ambiguous to things like 'click' to seperate them from the View implementation.
public class BasePresenter<V> {
protected V view;
public void attachView(V view) {
this.view = view;
}
}
public class MainPresenter extends BasePresenter<MainView> {
public void about() {
view.showToast("About was clicked");
}
public void cart() {
view.showToast("Cart was clicked");
}
}
The Activity implements the View interface. It's responsible for passing user events to the Presenter and actioning the Presenter commands.
public class MainActivity extends AppCompatActivity implements MainView {
private MainPresenter presenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
presenter = new MainPresenter();
presenter.attachView(this);
Button about = findViewById(R.id.button_about);
about.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
presenter.about();
}
});
Button cart = findViewById(R.id.button_cart);
cart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
presenter.cart();
}
});
}
@Override
public void showToast(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}
In this setup the Presenter no longer knows anything about Android (has no imports from the framework at all) and you are able to write unit tests for it which can run directly on the JVM without Android dependencies.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With