You're on the right track, and you're asking the right thing about static - whenever you notice that you have written this keyword, pause time and reflection.
The life of the leader should be tied directly to the "Activity" / "Fragment" section. Therefore, if the Activity is cleared by the GC, the same as the lead. This means that you should not contain a reference to the ApplicationContext in the presenter. It's nice to use ApplicationContext in Presenter, but it's important to break this link when destroying an Activity.
The presenter must also accept the View As Constructor option:
public class MainActivity extends Activity implements GameView{ public void onCreate(){ presenter = new GamePresenter(this); } }
and the lead looks like this:
public class GamePresenter { private final GameView view; public GamePresenter(GameView view){ this.view = view; } }
then you can notify the Presenter about activity life cycle events, for example:
public void onCreate(){ presenter.start(); } public void onDestroy(){ presenter.stop(); }
or in onResume/onPause - try to keep it symmetrical.
As a result, you have only 3 files:
(I take the code from another explanation I gave here , but the idea is the same.)
GamePresenter:
public class GamePresenter { private final GameView view; public GamePresenter(GameView view){ this.view = view; NetworkController.addObserver(this);
I don’t know exactly why you want to use ApplicationContext instead of an Activity context, but if there is no special reason for this, you can change the void start() method to void start(Context context) and just use the Activity context. For me this will make more sense and also eliminate the need to create a singlet in your Application class.
Gameview
is an interface
public interface GameView { void stopGame(); void moveRight(int pixels); }
GameFragment is a class that extends Fragment and implements GameView and has GamePresenter as a member.
public class GameFragment extends Fragment implements GameView { private GamePresenter presenter; @Override public void onCreate(Bundle savedInstanceState){ presenter = new GamePresenter(this); } }
The key to this approach is a clear understanding of the role of each file.
The fragment controls everything related to viewing (buttons, TextView, etc.). It informs the presenter about user interaction.
The host is the engine, it takes information from the view (in this case it is a fragment, but note that this template is well suited for dependency injection). This is not a coincidence. He doesn’t know that View is a fragment - he doesn’t care) and combines it with the information that he receives from "below" (comms, database etc), and then commands View accordingly.
A view is simply the interface through which the facilitator interacts with the view. Note that methods read as commands are not as questions (e.g. getViewState ()) and not to report (e.g. onPlayerPositionUpdated ()) - commands (e.g. movePlayerHere (int position)).