Software Engineer @ Originate
/**
* Interface for presenters that can be used with DemoViews
*/
public interface DemoPresenter<V extends DemoView> {
/**
* Method used to attach a view to the presenter
*/
void attachView(V view);
/**
* Method used to detach the previously attached view from the presenter
*/
void detachView();
}
/**
* Interface for views that can be attached to DemoPresenters
*/
public interface DemoView {
}
/**
* Base implementation of the DemoPresenter
*/
public class BasePresenter<V extends DemoView> implements DemoPresenter<V> {
private V view;
@Override
public void attachView(V view) {
// store the given DemoView in a private member variable
this.view = view;
}
@Override
public void detachView() {
// clear the stored DemoView
view = null;
}
}
/**
* Provides subclasses of BasePresenter access to the attached DemoView
*/
protected V getView() {
return view;
}
/**
* Informs subclasses of BasePresenter whether or not a DemoView is attached
*/
protected boolean isViewAttached() {
return view != null;
}
/**
* Base implementation of the DemoPresenter
*/
public class BasePresenter<V extends DemoView> implements DemoPresenter<V> {
private V view;
@Override
public void attachView(V view) {
// store the given DemoView in a private member variable
this.view = view;
}
@Override
public void detachView() {
// clear the stored DemoView
view = null;
}
/**
* Provides subclasses of BasePresenter access to the attached DemoView
*/
protected V getView() {
return view;
}
/**
* Informs subclasses of BasePresenter whether or not a DemoView is attached
*/
protected boolean isViewAttached() {
return view != null;
}
}
public class Course {
public String name;
public List<Student> students;
}
public class Student {
public String id; // unique student id
public String name;
}
/**
* Interface exposed to CoursePresenters for updating the course screen's UI
*/
public interface CourseView extends DemoView { }
/**
* Informs the view that the loading spinner should be hidden
*/
void hideLoadingSpinner();
/**
* Informs the view that the network error message should be displayed
*/
void showErrorMessage();
/**
* Informs the view of the student that has been found
*/
void studentFound(String studentName);
/**
* Informs the view that no student has been found with the given id number
*/
void studentNotFound(String number);
/**
* Informs the view that the title should be updated to the given title
*/
void updateViewTitle(String title);
/**
* Interface exposed to CoursePresenters for updating the course screen's UI
*/
public interface CourseView extends DemoView {
/**
* Informs the view that the loading spinner should be hidden
*/
void hideLoadingSpinner();
/**
* Informs the view that the network error message should be displayed
*/
void showErrorMessage();
/**
* Informs the view of the student that has been found
*/
void studentFound(String studentName);
/**
* Informs the view that no student has been found with the given id number
*/
void studentNotFound(String number);
/**
* Informs the view that the title should be updated to the given title
*/
void updateViewTitle(String title);
}
public class CourseActivity extends Activity implements CourseView
private CoursePresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
presenter = new CoursePresenter;
presenter.attachView(this);
}
@Override
protected void onDestroy() {
presenter.detachView();
super.onDestroy();
}
@OnClick(R.id.submit_button)
void onClick() {
presenter.findStudent(editTextView.getText().toString());
}
/* Implementation of CourseView methods */
}
public class CoursePresenter extends BasePresenter<CourseView> {
private List<Student> students;
@Override
public void attachView() {
super.attachView()
DataManager.loadCourse(new CallBack() {
@Override
public void onSuccess(List<Student> result) {
if (isViewAttached()) {
students = result;
getView().hideLoadingSpinner();
}
}
@Override
public void onError(Throwable error) {
if (isViewAttached()) {
getView().showErrorMessage();
}
}
});
}
}
@Override
public void detachView() {
roster = null;
super.detachView();
}
/**
* Passes the student's name back to the attached view
* @param the string representation of the matching student's name
*/
private void studentFound(String name) {
if (isViewAttached()) {
getView().studentFound(name);
}
}
/**
* Passes the id number that wasn't found back to the attached view
* @param the string representation of the searched id number
*/
private void studentNotFound(String number) {
if (isViewAttached()) {
getView().studentNotFound(number);
}
}
/**
* Checks to see if the the course contains a student
* with the matching id number
* and passes the result back to the attached view
*
* @param the string representation of the id number to lookup
*/
public void findStudent(String number) {
if (! TextUtils.isEmpty(number)) {
for (Student student : students) {
if (number.equals(student.id)) {
studentFound(student.name);
return;
}
}
}
studentNotFound(number);
}
// mock creation
DataManager mockedDataManager =
mock(DataManager.class);
// stub a method
List<Student> students =
new ArrayList<>();
when(mockDataManager.loadCourse())
.thenReturn(Callback.success(students));
// verify a method was called
verify(mockDataManager).loadCourse();
@Before
public void setup() {
DataManager mockDataManager = mock(DataManager.class);
presenter = new RosterPresenter(mockDataManager);
mockView = mock(CourseView.class);
}
@Test
public void testDetachView() {
assertFalse(presenter.isViewAttached());
assertNull(presenter.getView());
presenter.attachView(mockView);
assertTrue(presenter.isViewAttached());
assertNotNull(presenter.getView());
presenter.detachView();
assertFalse(presenter.isViewAttached());
assertNull(presenter.getView());
}
@Before
public void setup() {
DataManager mockDataManager = mock(DataManager.class);
presenter = new RosterPresenter(mockDataManager);
mockView = mock(CourseView.class);
}
@Test
public void testLoadCourseSuccess() {
when(mockDataManager.loadCourse())
.thenReturn(Callback.success(new ArrayList()));
presenter.attachView(mockView);
verify(mockDataManager).loadCourse();
verify(mockView).hideLoadingSpinner();
}
@Test
public void testLoadCourseFailure() {
when(mockDataManager.getPlayers(anyString()))
.thenReturn(Callback.error(new Throwable()));
presenter.attachView(mockView);
verify(mockDataManager).loadCourse();
verify(mockView).showErrorMessage();
}