Skip to content

Instantly share code, notes, and snippets.

@tonnylitao
Last active April 17, 2018 23:16
Show Gist options
  • Save tonnylitao/147e0f3955ab1d779f03ee8e8d51238c to your computer and use it in GitHub Desktop.
Save tonnylitao/147e0f3955ab1d779f03ee8e8d51238c to your computer and use it in GitHub Desktop.
Android MVP using interfaces to decouple.

#Android MVP

##1. Using MVP Android Activity in old time was God Entity which contained tons of business logic. But in MVP architecture, activity is just activity, it’s a native part managed by system. We strive not to disturb activity in business logic development by putting logic/io/computing… code into Presenter.

class HomeActivity extends AppCompatActivity {
    private HomeActivityPresenter mPresenter;
    //...
}

class HomeActivityPresenter {
    private HomeActivity mView;
    //...
}

##2. Using two interfaces to be more abstractive. Note: This methodology seems overdesigned for MVP.

HomeActivity concerns about the view logic. So MVPView interface is declared in HomeActivity.java. Same for Presenter.

//HomeActivity.java
interface MVPView {
	//view logic, such as setupView()
}

class HomeActivity extends AppCompatActivity implements MVPView {
    private MVPPresenter mPresenter;
    //...
}

//Presenter.java
interface MVPPresenter {
	//presenter logic, such as loadData()
}

class Presenter implements MVPPresenter {
    private MVPView mView;
    //...
}

##3. Another veriation(version). HomeActivity concerns about the presenter logic this time. So MVPPresenter interface is declared in HomeActivity.java. Same for Presenter.

//HomeActivity.java
interface MVPPresenter {
	//presenter logic
}

class HomeActivity extends AppCompatActivity implements MVPView {
    private MVPPresenter mPresenter;
    //...
}

//Presenter.java
interface MVPView {
	//view logic
}

class Presenter implements MVPPresenter {
    private MVPView mView;
    //...
}

###4. Which way should I use? It's difficult for us to choose, There is no absolute right or wrong for them. It becomes a disaster when your colleague chose the different one from you in the project.This means we have to make a smart decision.

In most UI case, Activity cares not only about controller logic but also view logic. If we declare these abstract interface into one place with MVP architecture, it seems much better.

interface HomeActivityMVP {
    interface Presenter {
        void loadData();
        void clearMVP();
    }
    
    interface View {
        void refresh(String string);
    }
    
}
 
class HomeActivity extends AppCompatActivity implements HomeActivityMVP.View {
    private HomeActivityMVP.Presenter mPresenter;
    //...
}

class Presenter implements HomeActivityMVP.Presenter {
    private HomeActivityMVP.View mView;
    //...
}
interface HomeActivityMVP {
interface Presenter {
void loadData();
void clearMVP();
}
interface View {
void refresh(String string);
}
}
public class HomeActivity extends AppCompatActivity implements HomeActivityMVP.View {
private HomeActivityMVP.Presenter mPresenter;
@Override
public void refresh(String string) {
Log.d("HomeActivity", string);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
mPresenter = (HomeActivityMVP.Presenter) new HomeActivityPresenter(this);
mPresenter.loadData();
}
@Override
protected void onDestroy() {
super.onDestroy();
mPresenter.clearMVP();
mPresenter = null;
}
}
class HomeActivityPresenter implements HomeActivityMVP.Presenter {
HomeActivityMVP.View mView;
HomeActivityPresenter(HomeActivityMVP.View view) {
mView = view;
}
@Override
public void loadData(){
//async operations
if (mView != null) {
mView.refresh("Hello");
}
}
@Override
public void clearMVP() {
mView = null;
}
}
@jon-dearaujo
Copy link

Nice gist!!
I am wondering if it is really decoupled if you directly instantiate the HomeActivityPresenter in the activity, even if you cast it back to a HomeActivityMVP.Presenter.
At the end, for tests, lets say, you would need to override the HomeActivityPresenter creation to use a stub.

Anyway, it looks nice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment