├── LICENSE.txt
├── README.md
├── chapter1-geoquiz
├── .gitignore
├── README.md
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── olerass
│ │ │ └── pfexample
│ │ │ └── android
│ │ │ └── geoquiz
│ │ │ └── ApplicationTest.java
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── olerass
│ │ │ │ └── pfexample
│ │ │ │ └── android
│ │ │ │ └── geoquiz
│ │ │ │ ├── domain
│ │ │ │ ├── event
│ │ │ │ │ ├── DataEvent.java
│ │ │ │ │ └── DataEventListener.java
│ │ │ │ └── question
│ │ │ │ │ ├── Question.java
│ │ │ │ │ ├── QuestionModel.java
│ │ │ │ │ ├── QuestionPresenter.java
│ │ │ │ │ ├── QuestionView.java
│ │ │ │ │ └── StandardQuestionModel.java
│ │ │ │ └── platform
│ │ │ │ ├── AndroidQuestionView.java
│ │ │ │ └── QuizActivity.java
│ │ └── res
│ │ │ ├── layout
│ │ │ └── activity_quiz.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-w820dp
│ │ │ └── dimens.xml
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── olerass
│ │ └── pfexample
│ │ └── android
│ │ └── geoquiz
│ │ └── domain
│ │ └── question
│ │ ├── QuestionPresenterTest.java
│ │ └── StandardQuestionModelTest.java
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshots.png
└── settings.gradle
├── chapter2-geoquiz-challenges
├── .gitignore
├── README.md
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── olerass
│ │ │ └── pfexample
│ │ │ └── android
│ │ │ └── geoquiz
│ │ │ └── ApplicationTest.java
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── olerass
│ │ │ │ └── pfexample
│ │ │ │ └── android
│ │ │ │ └── geoquiz
│ │ │ │ ├── domain
│ │ │ │ ├── event
│ │ │ │ │ ├── DataEvent.java
│ │ │ │ │ ├── DataEventListener.java
│ │ │ │ │ ├── Event.java
│ │ │ │ │ └── EventListener.java
│ │ │ │ └── question
│ │ │ │ │ ├── Question.java
│ │ │ │ │ ├── QuestionModel.java
│ │ │ │ │ ├── QuestionPresenter.java
│ │ │ │ │ ├── QuestionView.java
│ │ │ │ │ └── StandardQuestionModel.java
│ │ │ │ └── platform
│ │ │ │ ├── AndroidQuestionView.java
│ │ │ │ └── QuizActivity.java
│ │ └── res
│ │ │ ├── drawable-hdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── drawable-mdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── drawable-xhdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── drawable-xxhdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── layout
│ │ │ └── activity_quiz.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-w820dp
│ │ │ └── dimens.xml
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── olerass
│ │ └── pfexample
│ │ └── android
│ │ └── geoquiz
│ │ └── domain
│ │ └── question
│ │ ├── QuestionPresenterTest.java
│ │ └── StandardQuestionModelTest.java
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshots.png
└── settings.gradle
├── chapter2-geoquiz
├── .gitignore
├── README.md
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── olerass
│ │ │ └── pfexample
│ │ │ └── android
│ │ │ └── geoquiz
│ │ │ └── ApplicationTest.java
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── olerass
│ │ │ │ └── pfexample
│ │ │ │ └── android
│ │ │ │ └── geoquiz
│ │ │ │ ├── domain
│ │ │ │ ├── event
│ │ │ │ │ ├── DataEvent.java
│ │ │ │ │ ├── DataEventListener.java
│ │ │ │ │ ├── Event.java
│ │ │ │ │ └── EventListener.java
│ │ │ │ └── question
│ │ │ │ │ ├── Question.java
│ │ │ │ │ ├── QuestionModel.java
│ │ │ │ │ ├── QuestionPresenter.java
│ │ │ │ │ ├── QuestionView.java
│ │ │ │ │ └── StandardQuestionModel.java
│ │ │ │ └── platform
│ │ │ │ ├── AndroidQuestionView.java
│ │ │ │ └── QuizActivity.java
│ │ └── res
│ │ │ ├── drawable-hdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── drawable-mdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── drawable-xhdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── drawable-xxhdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── layout
│ │ │ └── activity_quiz.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-w820dp
│ │ │ └── dimens.xml
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── olerass
│ │ └── pfexample
│ │ └── android
│ │ └── geoquiz
│ │ └── domain
│ │ └── question
│ │ ├── QuestionPresenterTest.java
│ │ └── StandardQuestionModelTest.java
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshots.png
└── settings.gradle
├── chapter3-geoquiz
├── .gitignore
├── README.md
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── olerass
│ │ │ └── pfexample
│ │ │ └── android
│ │ │ └── geoquiz
│ │ │ └── ApplicationTest.java
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── olerass
│ │ │ │ └── pfexample
│ │ │ │ └── android
│ │ │ │ └── geoquiz
│ │ │ │ ├── domain
│ │ │ │ ├── event
│ │ │ │ │ ├── DataEvent.java
│ │ │ │ │ ├── DataEventListener.java
│ │ │ │ │ ├── Event.java
│ │ │ │ │ └── EventListener.java
│ │ │ │ ├── question
│ │ │ │ │ ├── Question.java
│ │ │ │ │ ├── QuestionModel.java
│ │ │ │ │ ├── QuestionPresenter.java
│ │ │ │ │ ├── QuestionView.java
│ │ │ │ │ └── StandardQuestionModel.java
│ │ │ │ └── state
│ │ │ │ │ ├── AndroidStateManager.java
│ │ │ │ │ ├── StateLoader.java
│ │ │ │ │ └── StateSaver.java
│ │ │ │ └── platform
│ │ │ │ ├── AndroidQuestionView.java
│ │ │ │ └── QuizActivity.java
│ │ └── res
│ │ │ ├── drawable-hdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── drawable-mdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── drawable-xhdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── drawable-xxhdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── layout-land
│ │ │ └── activity_quiz.xml
│ │ │ ├── layout
│ │ │ └── activity_quiz.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-w820dp
│ │ │ └── dimens.xml
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── olerass
│ │ └── pfexample
│ │ └── android
│ │ └── geoquiz
│ │ └── domain
│ │ ├── question
│ │ ├── QuestionPresenterTest.java
│ │ └── StandardQuestionModelTest.java
│ │ └── state
│ │ └── AndroidStateManagerTest.java
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshots.png
└── settings.gradle
├── chapter5-geoquiz-challenges
├── .gitignore
├── README.md
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── olerass
│ │ │ └── pfexample
│ │ │ └── android
│ │ │ └── geoquiz
│ │ │ └── ApplicationTest.java
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── olerass
│ │ │ │ └── pfexample
│ │ │ │ └── android
│ │ │ │ └── geoquiz
│ │ │ │ ├── domain
│ │ │ │ ├── cheat
│ │ │ │ │ ├── CheatModel.java
│ │ │ │ │ ├── CheatPresenter.java
│ │ │ │ │ ├── CheatView.java
│ │ │ │ │ └── StandardCheatModel.java
│ │ │ │ ├── event
│ │ │ │ │ ├── DataEvent.java
│ │ │ │ │ ├── DataEventListener.java
│ │ │ │ │ ├── Event.java
│ │ │ │ │ └── EventListener.java
│ │ │ │ ├── question
│ │ │ │ │ ├── Question.java
│ │ │ │ │ ├── QuestionModel.java
│ │ │ │ │ ├── QuestionPresenter.java
│ │ │ │ │ ├── QuestionView.java
│ │ │ │ │ └── StandardQuestionModel.java
│ │ │ │ └── state
│ │ │ │ │ ├── AndroidStateManager.java
│ │ │ │ │ ├── StateLoader.java
│ │ │ │ │ └── StateSaver.java
│ │ │ │ └── platform
│ │ │ │ ├── AndroidCheatView.java
│ │ │ │ ├── AndroidQuestionView.java
│ │ │ │ ├── CheatActivity.java
│ │ │ │ └── QuizActivity.java
│ │ └── res
│ │ │ ├── drawable-hdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── drawable-mdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── drawable-xhdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── drawable-xxhdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── layout-land
│ │ │ └── activity_quiz.xml
│ │ │ ├── layout
│ │ │ ├── activity_cheat.xml
│ │ │ └── activity_quiz.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-v21
│ │ │ └── styles.xml
│ │ │ ├── values-w820dp
│ │ │ └── dimens.xml
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── olerass
│ │ └── pfexample
│ │ └── android
│ │ └── geoquiz
│ │ └── domain
│ │ ├── cheat
│ │ ├── CheatPresenterTest.java
│ │ └── StandardCheatModelTest.java
│ │ ├── question
│ │ ├── QuestionPresenterTest.java
│ │ └── StandardQuestionModelTest.java
│ │ └── state
│ │ └── AndroidStateManagerTest.java
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshots.png
└── settings.gradle
├── chapter5-geoquiz
├── .gitignore
├── README.md
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── olerass
│ │ │ └── pfexample
│ │ │ └── android
│ │ │ └── geoquiz
│ │ │ └── ApplicationTest.java
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── olerass
│ │ │ │ └── pfexample
│ │ │ │ └── android
│ │ │ │ └── geoquiz
│ │ │ │ ├── domain
│ │ │ │ ├── cheat
│ │ │ │ │ ├── CheatModel.java
│ │ │ │ │ ├── CheatPresenter.java
│ │ │ │ │ ├── CheatView.java
│ │ │ │ │ └── StandardCheatModel.java
│ │ │ │ ├── event
│ │ │ │ │ ├── DataEvent.java
│ │ │ │ │ ├── DataEventListener.java
│ │ │ │ │ ├── Event.java
│ │ │ │ │ └── EventListener.java
│ │ │ │ ├── question
│ │ │ │ │ ├── Question.java
│ │ │ │ │ ├── QuestionModel.java
│ │ │ │ │ ├── QuestionPresenter.java
│ │ │ │ │ ├── QuestionView.java
│ │ │ │ │ └── StandardQuestionModel.java
│ │ │ │ └── state
│ │ │ │ │ ├── AndroidStateManager.java
│ │ │ │ │ ├── StateLoader.java
│ │ │ │ │ └── StateSaver.java
│ │ │ │ └── platform
│ │ │ │ ├── AndroidCheatView.java
│ │ │ │ ├── AndroidQuestionView.java
│ │ │ │ ├── CheatActivity.java
│ │ │ │ └── QuizActivity.java
│ │ └── res
│ │ │ ├── drawable-hdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── drawable-mdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── drawable-xhdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── drawable-xxhdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── layout-land
│ │ │ └── activity_quiz.xml
│ │ │ ├── layout
│ │ │ ├── activity_cheat.xml
│ │ │ └── activity_quiz.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-v21
│ │ │ └── styles.xml
│ │ │ ├── values-w820dp
│ │ │ └── dimens.xml
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── olerass
│ │ └── pfexample
│ │ └── android
│ │ └── geoquiz
│ │ └── domain
│ │ ├── cheat
│ │ ├── CheatPresenterTest.java
│ │ └── StandardCheatModelTest.java
│ │ ├── question
│ │ ├── QuestionPresenterTest.java
│ │ └── StandardQuestionModelTest.java
│ │ └── state
│ │ └── AndroidStateManagerTest.java
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshots.png
└── settings.gradle
├── chapter6-geoquiz-challenges
├── .gitignore
├── README.md
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── olerass
│ │ │ └── pfexample
│ │ │ └── android
│ │ │ └── geoquiz
│ │ │ └── ApplicationTest.java
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── olerass
│ │ │ │ └── pfexample
│ │ │ │ └── android
│ │ │ │ └── geoquiz
│ │ │ │ ├── domain
│ │ │ │ ├── cheat
│ │ │ │ │ ├── CheatModel.java
│ │ │ │ │ ├── CheatPresenter.java
│ │ │ │ │ ├── CheatView.java
│ │ │ │ │ └── StandardCheatModel.java
│ │ │ │ ├── event
│ │ │ │ │ ├── DataEvent.java
│ │ │ │ │ ├── DataEventListener.java
│ │ │ │ │ ├── Event.java
│ │ │ │ │ └── EventListener.java
│ │ │ │ ├── question
│ │ │ │ │ ├── Question.java
│ │ │ │ │ ├── QuestionModel.java
│ │ │ │ │ ├── QuestionPresenter.java
│ │ │ │ │ ├── QuestionView.java
│ │ │ │ │ └── StandardQuestionModel.java
│ │ │ │ └── state
│ │ │ │ │ ├── AndroidStateManager.java
│ │ │ │ │ ├── StateLoader.java
│ │ │ │ │ └── StateSaver.java
│ │ │ │ └── platform
│ │ │ │ ├── AndroidCheatView.java
│ │ │ │ ├── AndroidQuestionView.java
│ │ │ │ ├── CheatActivity.java
│ │ │ │ └── QuizActivity.java
│ │ └── res
│ │ │ ├── drawable-hdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── drawable-mdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── drawable-xhdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── drawable-xxhdpi
│ │ │ ├── arrow_left.png
│ │ │ └── arrow_right.png
│ │ │ ├── layout-land
│ │ │ └── activity_quiz.xml
│ │ │ ├── layout
│ │ │ ├── activity_cheat.xml
│ │ │ └── activity_quiz.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-v21
│ │ │ └── styles.xml
│ │ │ ├── values-w820dp
│ │ │ └── dimens.xml
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── olerass
│ │ └── pfexample
│ │ └── android
│ │ └── geoquiz
│ │ └── domain
│ │ ├── cheat
│ │ ├── CheatPresenterTest.java
│ │ └── StandardCheatModelTest.java
│ │ ├── question
│ │ ├── QuestionPresenterTest.java
│ │ └── StandardQuestionModelTest.java
│ │ └── state
│ │ └── AndroidStateManagerTest.java
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshots.png
└── settings.gradle
├── chapter7-criminalintent
├── .gitignore
├── README.md
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── olerass
│ │ │ └── pfexample
│ │ │ └── android
│ │ │ └── criminalintent
│ │ │ └── ApplicationTest.java
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── olerass
│ │ │ │ └── pfexample
│ │ │ │ └── android
│ │ │ │ └── criminalintent
│ │ │ │ ├── domain
│ │ │ │ ├── crime
│ │ │ │ │ ├── Crime.java
│ │ │ │ │ ├── CrimeModel.java
│ │ │ │ │ ├── CrimePresenter.java
│ │ │ │ │ ├── CrimeView.java
│ │ │ │ │ └── StandardCrimeModel.java
│ │ │ │ └── event
│ │ │ │ │ ├── DataEvent.java
│ │ │ │ │ └── DataEventListener.java
│ │ │ │ └── platform
│ │ │ │ ├── CrimeActivity.java
│ │ │ │ ├── CrimeFragment.java
│ │ │ │ └── FragmentCrimeView.java
│ │ └── res
│ │ │ ├── layout
│ │ │ ├── activity_crime.xml
│ │ │ └── fragment_crime.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-w820dp
│ │ │ └── dimens.xml
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── olerass
│ │ └── pfexample
│ │ └── android
│ │ └── criminalintent
│ │ └── domain
│ │ └── crime
│ │ ├── CrimePresenterTest.java
│ │ └── StandardCrimeModelTest.java
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshots.png
└── settings.gradle
├── chapter8-criminalintent-challenges
├── .gitignore
├── README.md
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── olerass
│ │ │ └── pfexample
│ │ │ └── android
│ │ │ └── criminalintent
│ │ │ └── ApplicationTest.java
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── olerass
│ │ │ │ └── pfexample
│ │ │ │ └── android
│ │ │ │ └── criminalintent
│ │ │ │ ├── domain
│ │ │ │ ├── crime
│ │ │ │ │ ├── Crime.java
│ │ │ │ │ ├── CrimeModel.java
│ │ │ │ │ ├── CrimePresenter.java
│ │ │ │ │ ├── CrimeView.java
│ │ │ │ │ └── StandardCrimeModel.java
│ │ │ │ └── event
│ │ │ │ │ ├── DataEvent.java
│ │ │ │ │ └── DataEventListener.java
│ │ │ │ └── platform
│ │ │ │ ├── CrimeActivity.java
│ │ │ │ ├── CrimeFragment.java
│ │ │ │ └── FragmentCrimeView.java
│ │ └── res
│ │ │ ├── layout-land
│ │ │ └── fragment_crime.xml
│ │ │ ├── layout
│ │ │ ├── activity_crime.xml
│ │ │ └── fragment_crime.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-w820dp
│ │ │ └── dimens.xml
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── olerass
│ │ └── pfexample
│ │ └── android
│ │ └── criminalintent
│ │ └── domain
│ │ └── crime
│ │ ├── CrimePresenterTest.java
│ │ └── StandardCrimeModelTest.java
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshots.png
└── settings.gradle
├── chapter8-criminalintent
├── .gitignore
├── README.md
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── olerass
│ │ │ └── pfexample
│ │ │ └── android
│ │ │ └── criminalintent
│ │ │ └── ApplicationTest.java
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── olerass
│ │ │ │ └── pfexample
│ │ │ │ └── android
│ │ │ │ └── criminalintent
│ │ │ │ ├── domain
│ │ │ │ ├── crime
│ │ │ │ │ ├── Crime.java
│ │ │ │ │ ├── CrimeModel.java
│ │ │ │ │ ├── CrimePresenter.java
│ │ │ │ │ ├── CrimeView.java
│ │ │ │ │ └── StandardCrimeModel.java
│ │ │ │ └── event
│ │ │ │ │ ├── DataEvent.java
│ │ │ │ │ └── DataEventListener.java
│ │ │ │ └── platform
│ │ │ │ ├── CrimeActivity.java
│ │ │ │ ├── CrimeFragment.java
│ │ │ │ └── FragmentCrimeView.java
│ │ └── res
│ │ │ ├── layout-land
│ │ │ └── fragment_crime.xml
│ │ │ ├── layout
│ │ │ ├── activity_crime.xml
│ │ │ └── fragment_crime.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-w820dp
│ │ │ └── dimens.xml
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── olerass
│ │ └── pfexample
│ │ └── android
│ │ └── criminalintent
│ │ └── domain
│ │ └── crime
│ │ ├── CrimePresenterTest.java
│ │ └── StandardCrimeModelTest.java
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshots.png
└── settings.gradle
└── chapter9-criminalintent
├── .gitignore
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── olerass
│ │ └── pfexample
│ │ └── android
│ │ └── criminalintent
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── olerass
│ │ │ └── pfexample
│ │ │ └── android
│ │ │ └── criminalintent
│ │ │ ├── domain
│ │ │ ├── crime
│ │ │ │ ├── Crime.java
│ │ │ │ ├── CrimeModel.java
│ │ │ │ ├── CrimePresenter.java
│ │ │ │ ├── CrimeView.java
│ │ │ │ └── StandardCrimeModel.java
│ │ │ ├── crimes
│ │ │ │ ├── CrimeLab.java
│ │ │ │ ├── CrimeListModel.java
│ │ │ │ ├── CrimeListPresenter.java
│ │ │ │ ├── CrimeListView.java
│ │ │ │ └── StandardCrimeListModel.java
│ │ │ └── event
│ │ │ │ ├── DataEvent.java
│ │ │ │ └── DataEventListener.java
│ │ │ └── platform
│ │ │ ├── SingleFragmentActivity.java
│ │ │ ├── crime
│ │ │ ├── CrimeActivity.java
│ │ │ ├── CrimeFragment.java
│ │ │ └── FragmentCrimeView.java
│ │ │ └── crimes
│ │ │ ├── CrimeListActivity.java
│ │ │ ├── CrimeListFragment.java
│ │ │ └── FragmentCrimeListView.java
│ └── res
│ │ ├── layout-land
│ │ └── fragment_crime.xml
│ │ ├── layout
│ │ ├── activity_fragment.xml
│ │ ├── fragment_crime.xml
│ │ ├── fragment_crime_list.xml
│ │ └── list_item_crime.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── olerass
│ └── pfexample
│ └── android
│ └── criminalintent
│ └── domain
│ ├── crime
│ ├── CrimeLabTest.java
│ ├── CrimePresenterTest.java
│ └── StandardCrimeModelTest.java
│ └── crimes
│ ├── CrimeListPresenterTest.java
│ └── StandardCrimeListModelTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshots.png
└── settings.gradle
/chapter1-geoquiz/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 |
--------------------------------------------------------------------------------
/chapter1-geoquiz/README.md:
--------------------------------------------------------------------------------
1 | # Presenter First Android - GeoQuiz Chapter 1
2 |
3 | Single-activity app that displays a question. The user may answer true or false and will be notified whether the answer was correct or not.
4 |
5 | 
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'me.tatarka.retrolambda'
3 |
4 | android {
5 | compileSdkVersion 22
6 | buildToolsVersion "23.0.2"
7 |
8 | defaultConfig {
9 | applicationId "com.olerass.pfexample.android.geoquiz"
10 | minSdkVersion 16
11 | targetSdkVersion 22
12 | versionCode 1
13 | versionName "1.0"
14 | }
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 | compileOptions {
22 | sourceCompatibility JavaVersion.VERSION_1_8
23 | targetCompatibility JavaVersion.VERSION_1_8
24 | }
25 | }
26 |
27 | dependencies {
28 | compile fileTree(dir: 'libs', include: ['*.jar'])
29 | compile 'com.android.support:appcompat-v7:22.2.1'
30 | testCompile 'junit:junit:4.12'
31 | testCompile 'org.mockito:mockito-core:1.10.19'
32 | }
33 |
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\olerass\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/src/androidTest/java/com/olerass/pfexample/android/geoquiz/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/DataEvent.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class DataEvent {
7 | private List> listeners = new ArrayList<>();
8 |
9 | public void addListener(DataEventListener listener) {
10 | listeners.add(listener);
11 | }
12 |
13 | public void dispatch(T data) {
14 | for (DataEventListener listener : listeners) {
15 | listener.onDispatch(data);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/DataEventListener.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | public interface DataEventListener {
4 | void onDispatch(T data);
5 | }
6 |
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/Question.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | public class Question {
4 | private String text;
5 | private boolean correctAnswer;
6 |
7 | public Question(String text, boolean correctAnswer) {
8 | this.text = text;
9 | this.correctAnswer = correctAnswer;
10 | }
11 |
12 | public String getText() {
13 | return text;
14 | }
15 |
16 | public boolean getCorrectAnswer() {
17 | return correctAnswer;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/QuestionModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | public interface QuestionModel {
4 | String getQuestionText();
5 | boolean isCorrectAnswer(boolean answer);
6 | }
7 |
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/QuestionPresenter.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | public class QuestionPresenter {
4 | private QuestionView view;
5 | private QuestionModel model;
6 |
7 | public QuestionPresenter(QuestionView view, QuestionModel model) {
8 | this.view = view;
9 | this.model = model;
10 | initialize();
11 | }
12 |
13 | private void initialize() {
14 | view.setQuestionText(model.getQuestionText());
15 |
16 | view.whenAnswerGiven(answer -> {
17 | if (model.isCorrectAnswer(answer)) {
18 | view.showCorrectAnswerMessage();
19 | } else {
20 | view.showIncorrectAnswerMessage();
21 | }
22 | });
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/QuestionView.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | import com.olerass.pfexample.android.geoquiz.domain.event.DataEventListener;
4 |
5 | public interface QuestionView {
6 | void setQuestionText(String question);
7 | void showCorrectAnswerMessage();
8 | void showIncorrectAnswerMessage();
9 |
10 | void whenAnswerGiven(DataEventListener listener);
11 | }
12 |
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/StandardQuestionModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | public class StandardQuestionModel implements QuestionModel {
4 | private Question question;
5 |
6 | public StandardQuestionModel(Question question) {
7 | this.question = question;
8 | }
9 |
10 | @Override
11 | public String getQuestionText() {
12 | return question.getText();
13 | }
14 |
15 | @Override
16 | public boolean isCorrectAnswer(boolean answer) {
17 | return answer == question.getCorrectAnswer();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter1-geoquiz/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter1-geoquiz/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter1-geoquiz/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter1-geoquiz/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter1-geoquiz/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | PFGeoQuiz
3 | Constantinople is the largest city in Turkey
4 | True
5 | False
6 | Correct!
7 | Incorrect!
8 |
9 |
--------------------------------------------------------------------------------
/chapter1-geoquiz/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/chapter1-geoquiz/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.5.0'
9 | classpath 'me.tatarka:gradle-retrolambda:3.2.4'
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/chapter1-geoquiz/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/chapter1-geoquiz/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter1-geoquiz/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/chapter1-geoquiz/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
7 |
--------------------------------------------------------------------------------
/chapter1-geoquiz/screenshots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter1-geoquiz/screenshots.png
--------------------------------------------------------------------------------
/chapter1-geoquiz/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 |
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/README.md:
--------------------------------------------------------------------------------
1 | # Presenter First Android - GeoQuiz Chapter 2 (Challenges)
2 |
3 | Chapter 2 app with added functionality for cycling both back and forth between the questions. Furthermore, the navigation buttons now use images and touching the textview advances the question.
4 |
5 | 
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'me.tatarka.retrolambda'
3 |
4 | android {
5 | compileSdkVersion 22
6 | buildToolsVersion "23.0.2"
7 |
8 | defaultConfig {
9 | applicationId "com.olerass.pfexample.android.geoquiz"
10 | minSdkVersion 16
11 | targetSdkVersion 22
12 | versionCode 1
13 | versionName "1.0"
14 | }
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 | compileOptions {
22 | sourceCompatibility JavaVersion.VERSION_1_8
23 | targetCompatibility JavaVersion.VERSION_1_8
24 | }
25 | }
26 |
27 | dependencies {
28 | compile fileTree(dir: 'libs', include: ['*.jar'])
29 | compile 'com.android.support:appcompat-v7:22.2.1'
30 | testCompile 'junit:junit:4.12'
31 | testCompile 'org.mockito:mockito-core:1.10.19'
32 | }
33 |
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\olerass\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/androidTest/java/com/olerass/pfexample/android/geoquiz/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/DataEvent.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class DataEvent {
7 | private List> listeners = new ArrayList<>();
8 |
9 | public void addListener(DataEventListener listener) {
10 | listeners.add(listener);
11 | }
12 |
13 | public void dispatch(T data) {
14 | for (DataEventListener listener : listeners) {
15 | listener.onDispatch(data);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/DataEventListener.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | public interface DataEventListener {
4 | void onDispatch(T data);
5 | }
6 |
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/Event.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class Event {
7 | private List listeners = new ArrayList<>();
8 |
9 | public void addListener(EventListener listener) {
10 | listeners.add(listener);
11 | }
12 |
13 | public void dispatch() {
14 | for (EventListener listener : listeners) {
15 | listener.onDispatch();
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/EventListener.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | public interface EventListener {
4 | void onDispatch();
5 | }
6 |
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/Question.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | public class Question {
4 | private String text;
5 | private boolean correctAnswer;
6 |
7 | public Question(String text, boolean correctAnswer) {
8 | this.text = text;
9 | this.correctAnswer = correctAnswer;
10 | }
11 |
12 | public String getText() {
13 | return text;
14 | }
15 |
16 | public boolean getCorrectAnswer() {
17 | return correctAnswer;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/QuestionModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | import com.olerass.pfexample.android.geoquiz.domain.event.EventListener;
4 |
5 | public interface QuestionModel {
6 | String getQuestionText();
7 | boolean isCorrectAnswer(boolean answer);
8 | void gotoNextQuestion();
9 | void gotoPreviousQuestion();
10 |
11 | void whenQuestionTextChanged(EventListener listener);
12 | }
13 |
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/QuestionView.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | import com.olerass.pfexample.android.geoquiz.domain.event.DataEventListener;
4 | import com.olerass.pfexample.android.geoquiz.domain.event.EventListener;
5 |
6 | public interface QuestionView {
7 | void setQuestionText(String question);
8 | void showCorrectAnswerMessage();
9 | void showIncorrectAnswerMessage();
10 |
11 | void whenAnswerGiven(DataEventListener listener);
12 | void whenNextQuestionRequested(EventListener listener);
13 | void whenPreviousQuestionRequested(EventListener listener);
14 | }
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/res/drawable-hdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz-challenges/app/src/main/res/drawable-hdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/res/drawable-hdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz-challenges/app/src/main/res/drawable-hdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/res/drawable-mdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz-challenges/app/src/main/res/drawable-mdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/res/drawable-mdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz-challenges/app/src/main/res/drawable-mdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/res/drawable-xhdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz-challenges/app/src/main/res/drawable-xhdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/res/drawable-xhdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz-challenges/app/src/main/res/drawable-xhdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/res/drawable-xxhdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz-challenges/app/src/main/res/drawable-xxhdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/res/drawable-xxhdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz-challenges/app/src/main/res/drawable-xxhdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz-challenges/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz-challenges/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz-challenges/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz-challenges/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz-challenges/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.5.0'
9 | classpath 'me.tatarka:gradle-retrolambda:3.2.4'
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz-challenges/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
7 |
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/screenshots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz-challenges/screenshots.png
--------------------------------------------------------------------------------
/chapter2-geoquiz-challenges/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/README.md:
--------------------------------------------------------------------------------
1 | # Presenter First Android - GeoQuiz Chapter 2
2 |
3 | Chapter 1 app expanded with functionality for showing 5 different questions and forwards-cycling through them using a next button.
4 |
5 | 
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'me.tatarka.retrolambda'
3 |
4 | android {
5 | compileSdkVersion 22
6 | buildToolsVersion "23.0.2"
7 |
8 | defaultConfig {
9 | applicationId "com.olerass.pfexample.android.geoquiz"
10 | minSdkVersion 16
11 | targetSdkVersion 22
12 | versionCode 1
13 | versionName "1.0"
14 | }
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 | compileOptions {
22 | sourceCompatibility JavaVersion.VERSION_1_8
23 | targetCompatibility JavaVersion.VERSION_1_8
24 | }
25 | }
26 |
27 | dependencies {
28 | compile fileTree(dir: 'libs', include: ['*.jar'])
29 | compile 'com.android.support:appcompat-v7:22.2.1'
30 | testCompile 'junit:junit:4.12'
31 | testCompile 'org.mockito:mockito-core:1.10.19'
32 | }
33 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\olerass\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/androidTest/java/com/olerass/pfexample/android/geoquiz/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/DataEvent.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class DataEvent {
7 | private List> listeners = new ArrayList<>();
8 |
9 | public void addListener(DataEventListener listener) {
10 | listeners.add(listener);
11 | }
12 |
13 | public void dispatch(T data) {
14 | for (DataEventListener listener : listeners) {
15 | listener.onDispatch(data);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/DataEventListener.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | public interface DataEventListener {
4 | void onDispatch(T data);
5 | }
6 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/Event.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class Event {
7 | private List listeners = new ArrayList<>();
8 |
9 | public void addListener(EventListener listener) {
10 | listeners.add(listener);
11 | }
12 |
13 | public void dispatch() {
14 | for (EventListener listener : listeners) {
15 | listener.onDispatch();
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/EventListener.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | public interface EventListener {
4 | void onDispatch();
5 | }
6 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/Question.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | public class Question {
4 | private String text;
5 | private boolean correctAnswer;
6 |
7 | public Question(String text, boolean correctAnswer) {
8 | this.text = text;
9 | this.correctAnswer = correctAnswer;
10 | }
11 |
12 | public String getText() {
13 | return text;
14 | }
15 |
16 | public boolean getCorrectAnswer() {
17 | return correctAnswer;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/QuestionModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | import com.olerass.pfexample.android.geoquiz.domain.event.EventListener;
4 |
5 | public interface QuestionModel {
6 | String getQuestionText();
7 | boolean isCorrectAnswer(boolean answer);
8 | void gotoNextQuestion();
9 |
10 | void whenQuestionTextChanged(EventListener listener);
11 | }
12 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/QuestionPresenter.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | public class QuestionPresenter {
4 | private QuestionView view;
5 | private QuestionModel model;
6 |
7 | public QuestionPresenter(QuestionView view, QuestionModel model) {
8 | this.view = view;
9 | this.model = model;
10 | initialize();
11 | }
12 |
13 | private void initialize() {
14 | syncViewToModel();
15 |
16 | view.whenAnswerGiven(answer -> {
17 | if (model.isCorrectAnswer(answer)) {
18 | view.showCorrectAnswerMessage();
19 | } else {
20 | view.showIncorrectAnswerMessage();
21 | }
22 | });
23 |
24 | view.whenNextQuestionRequested(model::gotoNextQuestion);
25 | model.whenQuestionTextChanged(this::syncViewToModel);
26 | }
27 |
28 | private void syncViewToModel() {
29 | view.setQuestionText(model.getQuestionText());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/QuestionView.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | import com.olerass.pfexample.android.geoquiz.domain.event.DataEventListener;
4 | import com.olerass.pfexample.android.geoquiz.domain.event.EventListener;
5 |
6 | public interface QuestionView {
7 | void setQuestionText(String question);
8 | void showCorrectAnswerMessage();
9 | void showIncorrectAnswerMessage();
10 |
11 | void whenAnswerGiven(DataEventListener listener);
12 | void whenNextQuestionRequested(EventListener listener);
13 | }
14 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/res/drawable-hdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz/app/src/main/res/drawable-hdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/res/drawable-hdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz/app/src/main/res/drawable-hdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/res/drawable-mdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz/app/src/main/res/drawable-mdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/res/drawable-mdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz/app/src/main/res/drawable-mdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/res/drawable-xhdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz/app/src/main/res/drawable-xhdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/res/drawable-xhdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz/app/src/main/res/drawable-xhdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/res/drawable-xxhdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz/app/src/main/res/drawable-xxhdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/res/drawable-xxhdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz/app/src/main/res/drawable-xxhdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | PFGeoQuiz
3 | True
4 | False
5 | Correct!
6 | Incorrect!
7 | Next
8 | The Pacific ocean is larger than the Atlantic Ocean.
9 | The Suez Canal connects the Red Sea and the Indian Ocean.
10 | The Amazon source of the Nile River is in Egypt.
11 | The Amazon River is the longest river in the Americas.
12 | Lake Baikal is the world\'s oldest and deepest freshwater lake.
13 |
14 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.5.0'
9 | classpath 'me.tatarka:gradle-retrolambda:3.2.4'
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/chapter2-geoquiz/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/chapter2-geoquiz/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
7 |
--------------------------------------------------------------------------------
/chapter2-geoquiz/screenshots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter2-geoquiz/screenshots.png
--------------------------------------------------------------------------------
/chapter2-geoquiz/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/README.md:
--------------------------------------------------------------------------------
1 | # Presenter First Android - GeoQuiz Chapter 3
2 |
3 | Chapter 2 app expanded with functionality for saving/restoring the active question across rotations by overriding `onSaveInstanceState`.
4 |
5 | 
6 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'me.tatarka.retrolambda'
3 |
4 | android {
5 | compileSdkVersion 22
6 | buildToolsVersion "23.0.2"
7 |
8 | defaultConfig {
9 | applicationId "com.olerass.pfexample.android.geoquiz"
10 | minSdkVersion 16
11 | targetSdkVersion 22
12 | versionCode 1
13 | versionName "1.0"
14 | }
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 | compileOptions {
22 | sourceCompatibility JavaVersion.VERSION_1_8
23 | targetCompatibility JavaVersion.VERSION_1_8
24 | }
25 | }
26 |
27 | dependencies {
28 | compile fileTree(dir: 'libs', include: ['*.jar'])
29 | compile 'com.android.support:appcompat-v7:22.2.1'
30 | testCompile 'junit:junit:4.12'
31 | testCompile 'org.mockito:mockito-core:1.10.19'
32 | }
33 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\olerass\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/androidTest/java/com/olerass/pfexample/android/geoquiz/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/DataEvent.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class DataEvent {
7 | private List> listeners = new ArrayList<>();
8 |
9 | public void addListener(DataEventListener listener) {
10 | listeners.add(listener);
11 | }
12 |
13 | public void dispatch(T data) {
14 | for (DataEventListener listener : listeners) {
15 | listener.onDispatch(data);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/DataEventListener.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | public interface DataEventListener {
4 | void onDispatch(T data);
5 | }
6 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/Event.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class Event {
7 | private List listeners = new ArrayList<>();
8 |
9 | public void addListener(EventListener listener) {
10 | listeners.add(listener);
11 | }
12 |
13 | public void dispatch() {
14 | for (EventListener listener : listeners) {
15 | listener.onDispatch();
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/EventListener.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | public interface EventListener {
4 | void onDispatch();
5 | }
6 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/Question.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | public class Question {
4 | private String text;
5 | private boolean correctAnswer;
6 |
7 | public Question(String text, boolean correctAnswer) {
8 | this.text = text;
9 | this.correctAnswer = correctAnswer;
10 | }
11 |
12 | public String getText() {
13 | return text;
14 | }
15 |
16 | public boolean getCorrectAnswer() {
17 | return correctAnswer;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/QuestionModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | import com.olerass.pfexample.android.geoquiz.domain.event.EventListener;
4 |
5 | public interface QuestionModel {
6 | String getQuestionText();
7 | boolean isCorrectAnswer(boolean answer);
8 | void gotoNextQuestion();
9 |
10 | void whenQuestionTextChanged(EventListener listener);
11 | }
12 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/QuestionPresenter.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | public class QuestionPresenter {
4 | private QuestionView view;
5 | private QuestionModel model;
6 |
7 | public QuestionPresenter(QuestionView view, QuestionModel model) {
8 | this.view = view;
9 | this.model = model;
10 | initialize();
11 | }
12 |
13 | private void initialize() {
14 | syncViewToModel();
15 |
16 | view.whenAnswerGiven(answer -> {
17 | if (model.isCorrectAnswer(answer)) {
18 | view.showCorrectAnswerMessage();
19 | } else {
20 | view.showIncorrectAnswerMessage();
21 | }
22 | });
23 |
24 | view.whenNextQuestionRequested(model::gotoNextQuestion);
25 | model.whenQuestionTextChanged(this::syncViewToModel);
26 | }
27 |
28 | private void syncViewToModel() {
29 | view.setQuestionText(model.getQuestionText());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/QuestionView.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | import com.olerass.pfexample.android.geoquiz.domain.event.DataEventListener;
4 | import com.olerass.pfexample.android.geoquiz.domain.event.EventListener;
5 |
6 | public interface QuestionView {
7 | void setQuestionText(String question);
8 | void showCorrectAnswerMessage();
9 | void showIncorrectAnswerMessage();
10 |
11 | void whenAnswerGiven(DataEventListener listener);
12 | void whenNextQuestionRequested(EventListener listener);
13 | }
14 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/state/AndroidStateManager.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.state;
2 |
3 | import android.os.Bundle;
4 |
5 | public class AndroidStateManager implements StateSaver, StateLoader {
6 | private Bundle bundle;
7 |
8 | public AndroidStateManager(Bundle bundle) {
9 | this.bundle = bundle;
10 | }
11 |
12 | @Override
13 | public void saveInt(String key, int value) {
14 | bundle.putInt(key, value);
15 | }
16 |
17 | @Override
18 | public int loadInt(String key, int defaultIfNotFound) {
19 | if (bundle == null) {
20 | return defaultIfNotFound;
21 | }
22 | return bundle.getInt(key, defaultIfNotFound);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/state/StateLoader.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.state;
2 |
3 | public interface StateLoader {
4 | int loadInt(String key, int defaultIfNotFound);
5 | }
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/state/StateSaver.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.state;
2 |
3 | public interface StateSaver {
4 | void saveInt(String key, int value);
5 | }
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/res/drawable-hdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter3-geoquiz/app/src/main/res/drawable-hdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/res/drawable-hdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter3-geoquiz/app/src/main/res/drawable-hdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/res/drawable-mdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter3-geoquiz/app/src/main/res/drawable-mdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/res/drawable-mdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter3-geoquiz/app/src/main/res/drawable-mdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/res/drawable-xhdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter3-geoquiz/app/src/main/res/drawable-xhdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/res/drawable-xhdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter3-geoquiz/app/src/main/res/drawable-xhdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/res/drawable-xxhdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter3-geoquiz/app/src/main/res/drawable-xxhdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/res/drawable-xxhdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter3-geoquiz/app/src/main/res/drawable-xxhdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter3-geoquiz/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter3-geoquiz/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter3-geoquiz/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter3-geoquiz/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter3-geoquiz/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | PFGeoQuiz
3 | True
4 | False
5 | Correct!
6 | Incorrect!
7 | Next
8 | The Pacific ocean is larger than the Atlantic Ocean.
9 | The Suez Canal connects the Red Sea and the Indian Ocean.
10 | The Amazon source of the Nile River is in Egypt.
11 | The Amazon River is the longest river in the Americas.
12 | Lake Baikal is the world\'s oldest and deepest freshwater lake.
13 |
14 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.5.0'
9 | classpath 'me.tatarka:gradle-retrolambda:3.2.4'
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/chapter3-geoquiz/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter3-geoquiz/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/chapter3-geoquiz/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
7 |
--------------------------------------------------------------------------------
/chapter3-geoquiz/screenshots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter3-geoquiz/screenshots.png
--------------------------------------------------------------------------------
/chapter3-geoquiz/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/README.md:
--------------------------------------------------------------------------------
1 | # Presenter First Android - GeoQuiz Chapter 5
2 |
3 | Chapter 5 app with added functionality that prevents users from cheating when cheating (!). This version ensures that the cheating status are saved across rotations. Furthermore it's saved for each question so that it's not possible to cycle through the questions to reset the status.
4 |
5 | 
6 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'me.tatarka.retrolambda'
3 |
4 | android {
5 | compileSdkVersion 22
6 | buildToolsVersion "23.0.2"
7 |
8 | defaultConfig {
9 | applicationId "com.olerass.pfexample.android.geoquiz"
10 | minSdkVersion 16
11 | targetSdkVersion 22
12 | versionCode 1
13 | versionName "1.0"
14 | }
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 | compileOptions {
22 | sourceCompatibility JavaVersion.VERSION_1_8
23 | targetCompatibility JavaVersion.VERSION_1_8
24 | }
25 | }
26 |
27 | dependencies {
28 | compile fileTree(dir: 'libs', include: ['*.jar'])
29 | compile 'com.android.support:appcompat-v7:22.2.1'
30 | testCompile 'junit:junit:4.12'
31 | testCompile 'org.mockito:mockito-core:1.10.19'
32 | }
33 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\olerass\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/androidTest/java/com/olerass/pfexample/android/geoquiz/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/cheat/CheatModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.cheat;
2 |
3 | public interface CheatModel {
4 | String getCorrectAnswer();
5 | void setAnswerShown(boolean answerShown);
6 | }
7 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/cheat/CheatPresenter.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.cheat;
2 |
3 | public class CheatPresenter {
4 | private CheatView view;
5 | private CheatModel model;
6 |
7 | public CheatPresenter(CheatView view, CheatModel model) {
8 | this.view = view;
9 | this.model = model;
10 | initialize();
11 | }
12 |
13 | private void initialize() {
14 | view.whenShowAnswerRequested(() -> {
15 | view.setAnswer(model.getCorrectAnswer());
16 | model.setAnswerShown(true);
17 | });
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/cheat/CheatView.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.cheat;
2 |
3 | import com.olerass.pfexample.android.geoquiz.domain.event.EventListener;
4 |
5 | public interface CheatView {
6 | void setAnswer(String answer);
7 |
8 | void whenShowAnswerRequested(EventListener listener);
9 | }
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/DataEvent.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class DataEvent {
7 | private List> listeners = new ArrayList<>();
8 |
9 | public void addListener(DataEventListener listener) {
10 | listeners.add(listener);
11 | }
12 |
13 | public void dispatch(T data) {
14 | for (DataEventListener listener : listeners) {
15 | listener.onDispatch(data);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/DataEventListener.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | public interface DataEventListener {
4 | void onDispatch(T data);
5 | }
6 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/Event.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class Event {
7 | private List listeners = new ArrayList<>();
8 |
9 | public void addListener(EventListener listener) {
10 | listeners.add(listener);
11 | }
12 |
13 | public void dispatch() {
14 | for (EventListener listener : listeners) {
15 | listener.onDispatch();
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/EventListener.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | public interface EventListener {
4 | void onDispatch();
5 | }
6 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/Question.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | public class Question {
4 | private String text;
5 | private boolean correctAnswer;
6 |
7 | public Question(String text, boolean correctAnswer) {
8 | this.text = text;
9 | this.correctAnswer = correctAnswer;
10 | }
11 |
12 | public String getText() {
13 | return text;
14 | }
15 |
16 | public boolean getCorrectAnswer() {
17 | return correctAnswer;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/QuestionModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | import com.olerass.pfexample.android.geoquiz.domain.event.EventListener;
4 |
5 | public interface QuestionModel {
6 | String getQuestionText();
7 | boolean hasCheatedOnCurrentQuestion();
8 | boolean isCorrectAnswer(boolean answer);
9 | void gotoNextQuestion();
10 |
11 | void cheatRequested();
12 | void whenQuestionTextChanged(EventListener listener);
13 | }
14 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/QuestionView.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | import com.olerass.pfexample.android.geoquiz.domain.event.DataEventListener;
4 | import com.olerass.pfexample.android.geoquiz.domain.event.EventListener;
5 |
6 | public interface QuestionView {
7 | void setQuestionText(String question);
8 | void showCorrectAnswerMessage();
9 | void showIncorrectAnswerMessage();
10 | void showCheaterMessage();
11 |
12 | void whenAnswerGiven(DataEventListener listener);
13 | void whenNextQuestionRequested(EventListener listener);
14 | void whenCheatRequested(EventListener listener);
15 | }
16 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/state/StateLoader.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.state;
2 |
3 | public interface StateLoader {
4 | int loadInt(String key, int defaultIfNotFound);
5 | boolean loadBool(String key, boolean defaultIfNotFound);
6 | }
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/state/StateSaver.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.state;
2 |
3 | public interface StateSaver {
4 | void saveInt(String key, int value);
5 | void saveBool(String key, boolean value);
6 | }
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/res/drawable-hdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz-challenges/app/src/main/res/drawable-hdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/res/drawable-hdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz-challenges/app/src/main/res/drawable-hdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/res/drawable-mdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz-challenges/app/src/main/res/drawable-mdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/res/drawable-mdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz-challenges/app/src/main/res/drawable-mdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/res/drawable-xhdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz-challenges/app/src/main/res/drawable-xhdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/res/drawable-xhdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz-challenges/app/src/main/res/drawable-xhdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/res/drawable-xxhdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz-challenges/app/src/main/res/drawable-xxhdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/res/drawable-xxhdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz-challenges/app/src/main/res/drawable-xxhdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz-challenges/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz-challenges/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz-challenges/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz-challenges/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz-challenges/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 | >
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 16dp
6 |
7 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.5.0'
9 | classpath 'me.tatarka:gradle-retrolambda:3.2.4'
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz-challenges/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
7 |
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/screenshots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz-challenges/screenshots.png
--------------------------------------------------------------------------------
/chapter5-geoquiz-challenges/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/README.md:
--------------------------------------------------------------------------------
1 | # Presenter First Android - GeoQuiz Chapter 5
2 |
3 | Chapter 3 app expanded with a second activity that allows cheating on a question to reveal its answer. Intents are used to pass data between the activities.
4 |
5 | 
6 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'me.tatarka.retrolambda'
3 |
4 | android {
5 | compileSdkVersion 22
6 | buildToolsVersion "23.0.2"
7 |
8 | defaultConfig {
9 | applicationId "com.olerass.pfexample.android.geoquiz"
10 | minSdkVersion 16
11 | targetSdkVersion 22
12 | versionCode 1
13 | versionName "1.0"
14 | }
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 | compileOptions {
22 | sourceCompatibility JavaVersion.VERSION_1_8
23 | targetCompatibility JavaVersion.VERSION_1_8
24 | }
25 | }
26 |
27 | dependencies {
28 | compile fileTree(dir: 'libs', include: ['*.jar'])
29 | compile 'com.android.support:appcompat-v7:22.2.1'
30 | testCompile 'junit:junit:4.12'
31 | testCompile 'org.mockito:mockito-core:1.10.19'
32 | }
33 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\olerass\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/androidTest/java/com/olerass/pfexample/android/geoquiz/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/cheat/CheatModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.cheat;
2 |
3 | public interface CheatModel {
4 | String getCorrectAnswer();
5 | void setAnswerShown(boolean answerShown);
6 | }
7 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/cheat/CheatPresenter.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.cheat;
2 |
3 | public class CheatPresenter {
4 | private CheatView view;
5 | private CheatModel model;
6 |
7 | public CheatPresenter(CheatView view, CheatModel model) {
8 | this.view = view;
9 | this.model = model;
10 | initialize();
11 | }
12 |
13 | private void initialize() {
14 | view.whenShowAnswerRequested(() -> {
15 | view.setAnswer(model.getCorrectAnswer());
16 | model.setAnswerShown(true);
17 | });
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/cheat/CheatView.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.cheat;
2 |
3 | import com.olerass.pfexample.android.geoquiz.domain.event.EventListener;
4 |
5 | public interface CheatView {
6 | void setAnswer(String answer);
7 |
8 | void whenShowAnswerRequested(EventListener listener);
9 | }
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/DataEvent.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class DataEvent {
7 | private List> listeners = new ArrayList<>();
8 |
9 | public void addListener(DataEventListener listener) {
10 | listeners.add(listener);
11 | }
12 |
13 | public void dispatch(T data) {
14 | for (DataEventListener listener : listeners) {
15 | listener.onDispatch(data);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/DataEventListener.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | public interface DataEventListener {
4 | void onDispatch(T data);
5 | }
6 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/Event.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class Event {
7 | private List listeners = new ArrayList<>();
8 |
9 | public void addListener(EventListener listener) {
10 | listeners.add(listener);
11 | }
12 |
13 | public void dispatch() {
14 | for (EventListener listener : listeners) {
15 | listener.onDispatch();
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/EventListener.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | public interface EventListener {
4 | void onDispatch();
5 | }
6 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/Question.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | public class Question {
4 | private String text;
5 | private boolean correctAnswer;
6 |
7 | public Question(String text, boolean correctAnswer) {
8 | this.text = text;
9 | this.correctAnswer = correctAnswer;
10 | }
11 |
12 | public String getText() {
13 | return text;
14 | }
15 |
16 | public boolean getCorrectAnswer() {
17 | return correctAnswer;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/QuestionModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | import com.olerass.pfexample.android.geoquiz.domain.event.EventListener;
4 |
5 | public interface QuestionModel {
6 | String getQuestionText();
7 | boolean isCheater();
8 | boolean isCorrectAnswer(boolean answer);
9 | void gotoNextQuestion();
10 |
11 | void cheatRequested();
12 | void whenQuestionTextChanged(EventListener listener);
13 | }
14 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/QuestionView.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | import com.olerass.pfexample.android.geoquiz.domain.event.DataEventListener;
4 | import com.olerass.pfexample.android.geoquiz.domain.event.EventListener;
5 |
6 | public interface QuestionView {
7 | void setQuestionText(String question);
8 | void showCorrectAnswerMessage();
9 | void showIncorrectAnswerMessage();
10 | void showCheaterMessage();
11 |
12 | void whenAnswerGiven(DataEventListener listener);
13 | void whenNextQuestionRequested(EventListener listener);
14 | void whenCheatRequested(EventListener listener);
15 | }
16 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/state/AndroidStateManager.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.state;
2 |
3 | import android.os.Bundle;
4 |
5 | public class AndroidStateManager implements StateSaver, StateLoader {
6 | private Bundle bundle;
7 |
8 | public AndroidStateManager(Bundle bundle) {
9 | this.bundle = bundle;
10 | }
11 |
12 | @Override
13 | public void saveInt(String key, int value) {
14 | bundle.putInt(key, value);
15 | }
16 |
17 | @Override
18 | public int loadInt(String key, int defaultIfNotFound) {
19 | if (bundle == null) {
20 | return defaultIfNotFound;
21 | }
22 | return bundle.getInt(key, defaultIfNotFound);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/state/StateLoader.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.state;
2 |
3 | public interface StateLoader {
4 | int loadInt(String key, int defaultIfNotFound);
5 | }
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/state/StateSaver.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.state;
2 |
3 | public interface StateSaver {
4 | void saveInt(String key, int value);
5 | }
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/res/drawable-hdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz/app/src/main/res/drawable-hdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/res/drawable-hdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz/app/src/main/res/drawable-hdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/res/drawable-mdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz/app/src/main/res/drawable-mdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/res/drawable-mdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz/app/src/main/res/drawable-mdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/res/drawable-xhdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz/app/src/main/res/drawable-xhdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/res/drawable-xhdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz/app/src/main/res/drawable-xhdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/res/drawable-xxhdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz/app/src/main/res/drawable-xxhdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/res/drawable-xxhdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz/app/src/main/res/drawable-xxhdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 | >
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 16dp
6 |
7 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.5.0'
9 | classpath 'me.tatarka:gradle-retrolambda:3.2.4'
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/chapter5-geoquiz/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/chapter5-geoquiz/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
7 |
--------------------------------------------------------------------------------
/chapter5-geoquiz/screenshots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter5-geoquiz/screenshots.png
--------------------------------------------------------------------------------
/chapter5-geoquiz/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/README.md:
--------------------------------------------------------------------------------
1 | # Presenter First Android - GeoQuiz Chapter 6 (Challenges)
2 |
3 | Chapter 5 app with an extra `TextView` in the cheat activity that shows the API level of the device.
4 |
5 | 
6 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'me.tatarka.retrolambda'
3 |
4 | android {
5 | compileSdkVersion 22
6 | buildToolsVersion "23.0.2"
7 |
8 | defaultConfig {
9 | applicationId "com.olerass.pfexample.android.geoquiz"
10 | minSdkVersion 16
11 | targetSdkVersion 22
12 | versionCode 1
13 | versionName "1.0"
14 | }
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 | compileOptions {
22 | sourceCompatibility JavaVersion.VERSION_1_8
23 | targetCompatibility JavaVersion.VERSION_1_8
24 | }
25 | }
26 |
27 | dependencies {
28 | compile fileTree(dir: 'libs', include: ['*.jar'])
29 | compile 'com.android.support:appcompat-v7:22.2.1'
30 | testCompile 'junit:junit:4.12'
31 | testCompile 'org.mockito:mockito-core:1.10.19'
32 | }
33 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\olerass\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/androidTest/java/com/olerass/pfexample/android/geoquiz/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/cheat/CheatModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.cheat;
2 |
3 | public interface CheatModel {
4 | String getCorrectAnswer();
5 | void setAnswerShown(boolean answerShown);
6 | }
7 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/cheat/CheatPresenter.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.cheat;
2 |
3 | public class CheatPresenter {
4 | private CheatView view;
5 | private CheatModel model;
6 |
7 | public CheatPresenter(CheatView view, CheatModel model) {
8 | this.view = view;
9 | this.model = model;
10 | initialize();
11 | }
12 |
13 | private void initialize() {
14 | view.whenShowAnswerRequested(() -> {
15 | view.setAnswer(model.getCorrectAnswer());
16 | model.setAnswerShown(true);
17 | });
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/cheat/CheatView.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.cheat;
2 |
3 | import com.olerass.pfexample.android.geoquiz.domain.event.EventListener;
4 |
5 | public interface CheatView {
6 | void setAnswer(String answer);
7 |
8 | void whenShowAnswerRequested(EventListener listener);
9 | }
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/DataEvent.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class DataEvent {
7 | private List> listeners = new ArrayList<>();
8 |
9 | public void addListener(DataEventListener listener) {
10 | listeners.add(listener);
11 | }
12 |
13 | public void dispatch(T data) {
14 | for (DataEventListener listener : listeners) {
15 | listener.onDispatch(data);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/DataEventListener.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | public interface DataEventListener {
4 | void onDispatch(T data);
5 | }
6 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/Event.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class Event {
7 | private List listeners = new ArrayList<>();
8 |
9 | public void addListener(EventListener listener) {
10 | listeners.add(listener);
11 | }
12 |
13 | public void dispatch() {
14 | for (EventListener listener : listeners) {
15 | listener.onDispatch();
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/event/EventListener.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.event;
2 |
3 | public interface EventListener {
4 | void onDispatch();
5 | }
6 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/Question.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | public class Question {
4 | private String text;
5 | private boolean correctAnswer;
6 |
7 | public Question(String text, boolean correctAnswer) {
8 | this.text = text;
9 | this.correctAnswer = correctAnswer;
10 | }
11 |
12 | public String getText() {
13 | return text;
14 | }
15 |
16 | public boolean getCorrectAnswer() {
17 | return correctAnswer;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/QuestionModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | import com.olerass.pfexample.android.geoquiz.domain.event.EventListener;
4 |
5 | public interface QuestionModel {
6 | String getQuestionText();
7 | boolean isCheater();
8 | boolean isCorrectAnswer(boolean answer);
9 | void gotoNextQuestion();
10 |
11 | void cheatRequested();
12 | void whenQuestionTextChanged(EventListener listener);
13 | }
14 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/question/QuestionView.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.question;
2 |
3 | import com.olerass.pfexample.android.geoquiz.domain.event.DataEventListener;
4 | import com.olerass.pfexample.android.geoquiz.domain.event.EventListener;
5 |
6 | public interface QuestionView {
7 | void setQuestionText(String question);
8 | void showCorrectAnswerMessage();
9 | void showIncorrectAnswerMessage();
10 | void showCheaterMessage();
11 |
12 | void whenAnswerGiven(DataEventListener listener);
13 | void whenNextQuestionRequested(EventListener listener);
14 | void whenCheatRequested(EventListener listener);
15 | }
16 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/state/AndroidStateManager.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.state;
2 |
3 | import android.os.Bundle;
4 |
5 | public class AndroidStateManager implements StateSaver, StateLoader {
6 | private Bundle bundle;
7 |
8 | public AndroidStateManager(Bundle bundle) {
9 | this.bundle = bundle;
10 | }
11 |
12 | @Override
13 | public void saveInt(String key, int value) {
14 | bundle.putInt(key, value);
15 | }
16 |
17 | @Override
18 | public int loadInt(String key, int defaultIfNotFound) {
19 | if (bundle == null) {
20 | return defaultIfNotFound;
21 | }
22 | return bundle.getInt(key, defaultIfNotFound);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/state/StateLoader.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.state;
2 |
3 | public interface StateLoader {
4 | int loadInt(String key, int defaultIfNotFound);
5 | }
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/java/com/olerass/pfexample/android/geoquiz/domain/state/StateSaver.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.geoquiz.domain.state;
2 |
3 | public interface StateSaver {
4 | void saveInt(String key, int value);
5 | }
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/res/drawable-hdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter6-geoquiz-challenges/app/src/main/res/drawable-hdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/res/drawable-hdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter6-geoquiz-challenges/app/src/main/res/drawable-hdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/res/drawable-mdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter6-geoquiz-challenges/app/src/main/res/drawable-mdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/res/drawable-mdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter6-geoquiz-challenges/app/src/main/res/drawable-mdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/res/drawable-xhdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter6-geoquiz-challenges/app/src/main/res/drawable-xhdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/res/drawable-xhdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter6-geoquiz-challenges/app/src/main/res/drawable-xhdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/res/drawable-xxhdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter6-geoquiz-challenges/app/src/main/res/drawable-xxhdpi/arrow_left.png
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/res/drawable-xxhdpi/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter6-geoquiz-challenges/app/src/main/res/drawable-xxhdpi/arrow_right.png
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter6-geoquiz-challenges/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter6-geoquiz-challenges/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter6-geoquiz-challenges/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter6-geoquiz-challenges/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter6-geoquiz-challenges/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 | >
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 16dp
6 |
7 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.5.0'
9 | classpath 'me.tatarka:gradle-retrolambda:3.2.4'
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter6-geoquiz-challenges/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
7 |
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/screenshots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter6-geoquiz-challenges/screenshots.png
--------------------------------------------------------------------------------
/chapter6-geoquiz-challenges/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/README.md:
--------------------------------------------------------------------------------
1 | # Presenter First Android - CriminalIntent Chapter 7
2 |
3 | Single-activity app that allows entering a crime title (the crime edit view). The title is synced with a in-memory model behind the scenes. Not much UI yet, but a lot of the domain classes are created to prepare for the following chapters.
4 |
5 | 
6 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\olerass\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/androidTest/java/com/olerass/pfexample/android/criminalintent/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/Crime.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | import java.util.UUID;
4 |
5 | public class Crime {
6 | private UUID id;
7 | private String title;
8 |
9 | public Crime() {
10 | id = UUID.randomUUID();
11 | }
12 |
13 | public UUID getId() {
14 | return id;
15 | }
16 |
17 | public String getTitle() {
18 | return title;
19 | }
20 |
21 | public void setTitle(String title) {
22 | this.title = title;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/CrimeModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | public interface CrimeModel {
4 | void setTitle(String title);
5 | }
6 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/CrimePresenter.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | public class CrimePresenter {
4 | private CrimeView view;
5 | private CrimeModel model;
6 |
7 | public CrimePresenter(CrimeView view, CrimeModel model) {
8 | this.view = view;
9 | this.model = model;
10 | initialize();
11 | }
12 |
13 | private void initialize() {
14 | view.whenTitleChanged(model::setTitle);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/CrimeView.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | import com.olerass.pfexample.android.criminalintent.domain.event.DataEventListener;
4 |
5 | public interface CrimeView {
6 | void whenTitleChanged(DataEventListener listener);
7 | }
8 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/StandardCrimeModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | public class StandardCrimeModel implements CrimeModel {
4 | private Crime crime;
5 |
6 | public StandardCrimeModel(Crime crime) {
7 | this.crime = crime;
8 | }
9 |
10 | @Override
11 | public void setTitle(String title) {
12 | crime.setTitle(title);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/event/DataEvent.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.event;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class DataEvent {
7 | private List> listeners = new ArrayList<>();
8 |
9 | public void addListener(DataEventListener listener) {
10 | listeners.add(listener);
11 | }
12 |
13 | public void dispatch(T data) {
14 | for (DataEventListener listener : listeners) {
15 | listener.onDispatch(data);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/event/DataEventListener.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.event;
2 |
3 | public interface DataEventListener {
4 | void onDispatch(T data);
5 | }
6 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/platform/CrimeActivity.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.platform;
2 |
3 | import android.support.v4.app.Fragment;
4 | import android.support.v4.app.FragmentManager;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.os.Bundle;
7 |
8 | import com.olerass.pfexample.android.criminalintent.R;
9 |
10 | public class CrimeActivity extends AppCompatActivity {
11 | @Override
12 | protected void onCreate(Bundle savedInstanceState) {
13 | super.onCreate(savedInstanceState);
14 | setContentView(R.layout.activity_crime);
15 |
16 | FragmentManager fm = getSupportFragmentManager();
17 | Fragment fragment = fm.findFragmentById(R.id.fragment_container);
18 | if (fragment == null) {
19 | fragment = new CrimeFragment();
20 | fm.beginTransaction().add(R.id.fragment_container, fragment).commit();
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/res/layout/activity_crime.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/res/layout/fragment_crime.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
11 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter7-criminalintent/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter7-criminalintent/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter7-criminalintent/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter7-criminalintent/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter7-criminalintent/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | CriminalIntent
3 | Enter a title for the crime.
4 |
5 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/test/java/com/olerass/pfexample/android/criminalintent/domain/crime/CrimePresenterTest.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | import com.olerass.pfexample.android.criminalintent.domain.event.DataEventListener;
4 |
5 | import org.junit.Test;
6 | import org.mockito.ArgumentCaptor;
7 |
8 | import static org.mockito.Mockito.mock;
9 | import static org.mockito.Mockito.verify;
10 |
11 | public class CrimePresenterTest {
12 | @Test
13 | public void updatesModelWithTitleFromView_whenItChanges() {
14 | CrimeView view = mock(CrimeView.class);
15 | CrimeModel model = mock(CrimeModel.class);
16 | new CrimePresenter(view, model);
17 |
18 | ArgumentCaptor> argument = ArgumentCaptor.forClass((Class)DataEventListener.class);
19 | verify(view).whenTitleChanged(argument.capture());
20 | argument.getValue().onDispatch("title");
21 |
22 | verify(model).setTitle("title");
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/app/src/test/java/com/olerass/pfexample/android/criminalintent/domain/crime/StandardCrimeModelTest.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.hamcrest.CoreMatchers.equalTo;
6 | import static org.hamcrest.CoreMatchers.is;
7 | import static org.hamcrest.MatcherAssert.assertThat;
8 |
9 | public class StandardCrimeModelTest {
10 | @Test
11 | public void setTitle_setsTheTitleInBackingCrime_whenCalled() {
12 | Crime crime = new Crime();
13 | StandardCrimeModel model = new StandardCrimeModel(crime);
14 |
15 | model.setTitle("title");
16 | assertThat(crime.getTitle(), is(equalTo("title")));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.5.0'
9 | classpath 'me.tatarka:gradle-retrolambda:3.2.4'
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/chapter7-criminalintent/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter7-criminalintent/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/chapter7-criminalintent/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
7 |
--------------------------------------------------------------------------------
/chapter7-criminalintent/screenshots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter7-criminalintent/screenshots.png
--------------------------------------------------------------------------------
/chapter7-criminalintent/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/README.md:
--------------------------------------------------------------------------------
1 | # Presenter First Android - CriminalIntent Chapter 8 (Challenges)
2 |
3 | Chapter 8 app with a custom crime date format using `DateFormat.format`
4 |
5 | 
6 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\olerass\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/androidTest/java/com/olerass/pfexample/android/criminalintent/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/Crime.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | import java.util.Date;
4 | import java.util.UUID;
5 |
6 | public class Crime {
7 | private UUID id;
8 | private String title;
9 | private Date date;
10 | private boolean solved;
11 |
12 | public Crime() {
13 | id = UUID.randomUUID();
14 | date = new Date();
15 | }
16 |
17 | public UUID getId() {
18 | return id;
19 | }
20 |
21 | public String getTitle() {
22 | return title;
23 | }
24 |
25 | public void setTitle(String title) {
26 | this.title = title;
27 | }
28 |
29 | public Date getDate() {
30 | return date;
31 | }
32 |
33 | public void setDate(Date date) {
34 | this.date = date;
35 | }
36 |
37 | public boolean isSolved() {
38 | return solved;
39 | }
40 |
41 | public void setSolved(boolean solved) {
42 | this.solved = solved;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/CrimeModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | import java.util.Date;
4 |
5 | public interface CrimeModel {
6 | Date getDate();
7 | void setTitle(String title);
8 | void setSolved(boolean solved);
9 | }
10 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/CrimePresenter.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | public class CrimePresenter {
4 | private CrimeView view;
5 | private CrimeModel model;
6 |
7 | public CrimePresenter(CrimeView view, CrimeModel model) {
8 | this.view = view;
9 | this.model = model;
10 | initialize();
11 | }
12 |
13 | private void initialize() {
14 | view.setDate(model.getDate());
15 | view.disableDateInteraction();
16 |
17 | view.whenTitleChanged(model::setTitle);
18 | view.whenSolvedChanged(model::setSolved);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/CrimeView.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | import com.olerass.pfexample.android.criminalintent.domain.event.DataEventListener;
4 |
5 | import java.util.Date;
6 |
7 | public interface CrimeView {
8 | void setDate(Date date);
9 | void disableDateInteraction();
10 |
11 | void whenTitleChanged(DataEventListener listener);
12 | void whenSolvedChanged(DataEventListener listener);
13 | }
14 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/StandardCrimeModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | import java.util.Date;
4 |
5 | public class StandardCrimeModel implements CrimeModel {
6 | private Crime crime;
7 |
8 | public StandardCrimeModel(Crime crime) {
9 | this.crime = crime;
10 | }
11 |
12 | @Override
13 | public Date getDate() {
14 | return crime.getDate();
15 | }
16 |
17 | @Override
18 | public void setTitle(String title) {
19 | crime.setTitle(title);
20 | }
21 |
22 | @Override
23 | public void setSolved(boolean solved) {
24 | crime.setSolved(solved);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/event/DataEvent.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.event;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class DataEvent {
7 | private List> listeners = new ArrayList<>();
8 |
9 | public void addListener(DataEventListener listener) {
10 | listeners.add(listener);
11 | }
12 |
13 | public void dispatch(T data) {
14 | for (DataEventListener listener : listeners) {
15 | listener.onDispatch(data);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/event/DataEventListener.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.event;
2 |
3 | public interface DataEventListener {
4 | void onDispatch(T data);
5 | }
6 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/java/com/olerass/pfexample/android/criminalintent/platform/CrimeActivity.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.platform;
2 |
3 | import android.support.v4.app.Fragment;
4 | import android.support.v4.app.FragmentManager;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.os.Bundle;
7 |
8 | import com.olerass.pfexample.android.criminalintent.R;
9 |
10 | public class CrimeActivity extends AppCompatActivity {
11 | @Override
12 | protected void onCreate(Bundle savedInstanceState) {
13 | super.onCreate(savedInstanceState);
14 | setContentView(R.layout.activity_crime);
15 |
16 | FragmentManager fm = getSupportFragmentManager();
17 | Fragment fragment = fm.findFragmentById(R.id.fragment_container);
18 | if (fragment == null) {
19 | fragment = new CrimeFragment();
20 | fm.beginTransaction().add(R.id.fragment_container, fragment).commit();
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/res/layout/activity_crime.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter8-criminalintent-challenges/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter8-criminalintent-challenges/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter8-criminalintent-challenges/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter8-criminalintent-challenges/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter8-criminalintent-challenges/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | CriminalIntent
3 | Enter a title for the crime.
4 | Title
5 | Details
6 | Solved
7 |
8 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.5.0'
9 | classpath 'me.tatarka:gradle-retrolambda:3.2.4'
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter8-criminalintent-challenges/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
7 |
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/screenshots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter8-criminalintent-challenges/screenshots.png
--------------------------------------------------------------------------------
/chapter8-criminalintent-challenges/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/README.md:
--------------------------------------------------------------------------------
1 | # Presenter First Android - CriminalIntent Chapter 8
2 |
3 | Chapter 7 app expanded with more fields in the crime view including a date and solved status.
4 |
5 | 
6 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\olerass\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/androidTest/java/com/olerass/pfexample/android/criminalintent/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/Crime.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | import java.util.Date;
4 | import java.util.UUID;
5 |
6 | public class Crime {
7 | private UUID id;
8 | private String title;
9 | private Date date;
10 | private boolean solved;
11 |
12 | public Crime() {
13 | id = UUID.randomUUID();
14 | date = new Date();
15 | }
16 |
17 | public UUID getId() {
18 | return id;
19 | }
20 |
21 | public String getTitle() {
22 | return title;
23 | }
24 |
25 | public void setTitle(String title) {
26 | this.title = title;
27 | }
28 |
29 | public Date getDate() {
30 | return date;
31 | }
32 |
33 | public void setDate(Date date) {
34 | this.date = date;
35 | }
36 |
37 | public boolean isSolved() {
38 | return solved;
39 | }
40 |
41 | public void setSolved(boolean solved) {
42 | this.solved = solved;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/CrimeModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | import java.util.Date;
4 |
5 | public interface CrimeModel {
6 | Date getDate();
7 | void setTitle(String title);
8 | void setSolved(boolean solved);
9 | }
10 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/CrimePresenter.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | public class CrimePresenter {
4 | private CrimeView view;
5 | private CrimeModel model;
6 |
7 | public CrimePresenter(CrimeView view, CrimeModel model) {
8 | this.view = view;
9 | this.model = model;
10 | initialize();
11 | }
12 |
13 | private void initialize() {
14 | view.setDate(model.getDate());
15 | view.disableDateInteraction();
16 |
17 | view.whenTitleChanged(model::setTitle);
18 | view.whenSolvedChanged(model::setSolved);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/CrimeView.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | import com.olerass.pfexample.android.criminalintent.domain.event.DataEventListener;
4 |
5 | import java.util.Date;
6 |
7 | public interface CrimeView {
8 | void setDate(Date date);
9 | void disableDateInteraction();
10 |
11 | void whenTitleChanged(DataEventListener listener);
12 | void whenSolvedChanged(DataEventListener listener);
13 | }
14 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/StandardCrimeModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | import java.util.Date;
4 |
5 | public class StandardCrimeModel implements CrimeModel {
6 | private Crime crime;
7 |
8 | public StandardCrimeModel(Crime crime) {
9 | this.crime = crime;
10 | }
11 |
12 | @Override
13 | public Date getDate() {
14 | return crime.getDate();
15 | }
16 |
17 | @Override
18 | public void setTitle(String title) {
19 | crime.setTitle(title);
20 | }
21 |
22 | @Override
23 | public void setSolved(boolean solved) {
24 | crime.setSolved(solved);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/event/DataEvent.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.event;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class DataEvent {
7 | private List> listeners = new ArrayList<>();
8 |
9 | public void addListener(DataEventListener listener) {
10 | listeners.add(listener);
11 | }
12 |
13 | public void dispatch(T data) {
14 | for (DataEventListener listener : listeners) {
15 | listener.onDispatch(data);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/event/DataEventListener.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.event;
2 |
3 | public interface DataEventListener {
4 | void onDispatch(T data);
5 | }
6 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/platform/CrimeActivity.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.platform;
2 |
3 | import android.support.v4.app.Fragment;
4 | import android.support.v4.app.FragmentManager;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.os.Bundle;
7 |
8 | import com.olerass.pfexample.android.criminalintent.R;
9 |
10 | public class CrimeActivity extends AppCompatActivity {
11 | @Override
12 | protected void onCreate(Bundle savedInstanceState) {
13 | super.onCreate(savedInstanceState);
14 | setContentView(R.layout.activity_crime);
15 |
16 | FragmentManager fm = getSupportFragmentManager();
17 | Fragment fragment = fm.findFragmentById(R.id.fragment_container);
18 | if (fragment == null) {
19 | fragment = new CrimeFragment();
20 | fm.beginTransaction().add(R.id.fragment_container, fragment).commit();
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/res/layout/activity_crime.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter8-criminalintent/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter8-criminalintent/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter8-criminalintent/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter8-criminalintent/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter8-criminalintent/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | CriminalIntent
3 | Enter a title for the crime.
4 | Title
5 | Details
6 | Solved
7 |
8 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.5.0'
9 | classpath 'me.tatarka:gradle-retrolambda:3.2.4'
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/chapter8-criminalintent/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter8-criminalintent/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/chapter8-criminalintent/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
7 |
--------------------------------------------------------------------------------
/chapter8-criminalintent/screenshots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter8-criminalintent/screenshots.png
--------------------------------------------------------------------------------
/chapter8-criminalintent/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/README.md:
--------------------------------------------------------------------------------
1 | # Presenter First Android - CriminalIntent Chapter 9
2 |
3 | Chapter 8 app expanded with a new activity for displaying a list of crimes using a `RecyclerView`. The crime view is not connected to the list view yet.
4 |
5 | 
6 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\olerass\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/androidTest/java/com/olerass/pfexample/android/criminalintent/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/Crime.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | import java.util.Date;
4 | import java.util.UUID;
5 |
6 | public class Crime {
7 | private UUID id;
8 | private String title;
9 | private Date date;
10 | private boolean solved;
11 |
12 | public Crime() {
13 | id = UUID.randomUUID();
14 | date = new Date();
15 | }
16 |
17 | public UUID getId() {
18 | return id;
19 | }
20 |
21 | public String getTitle() {
22 | return title;
23 | }
24 |
25 | public void setTitle(String title) {
26 | this.title = title;
27 | }
28 |
29 | public Date getDate() {
30 | return date;
31 | }
32 |
33 | public void setDate(Date date) {
34 | this.date = date;
35 | }
36 |
37 | public boolean isSolved() {
38 | return solved;
39 | }
40 |
41 | public void setSolved(boolean solved) {
42 | this.solved = solved;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/CrimeModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | import java.util.Date;
4 |
5 | public interface CrimeModel {
6 | Date getDate();
7 | void setTitle(String title);
8 | void setSolved(boolean solved);
9 | }
10 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/CrimePresenter.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | public class CrimePresenter {
4 | private CrimeView view;
5 | private CrimeModel model;
6 |
7 | public CrimePresenter(CrimeView view, CrimeModel model) {
8 | this.view = view;
9 | this.model = model;
10 | initialize();
11 | }
12 |
13 | private void initialize() {
14 | view.setDate(model.getDate());
15 | view.disableDateInteraction();
16 |
17 | view.whenTitleChanged(model::setTitle);
18 | view.whenSolvedChanged(model::setSolved);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/CrimeView.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | import com.olerass.pfexample.android.criminalintent.domain.event.DataEventListener;
4 |
5 | import java.util.Date;
6 |
7 | public interface CrimeView {
8 | void setDate(Date date);
9 | void disableDateInteraction();
10 |
11 | void whenTitleChanged(DataEventListener listener);
12 | void whenSolvedChanged(DataEventListener listener);
13 | }
14 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crime/StandardCrimeModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crime;
2 |
3 | import java.util.Date;
4 |
5 | public class StandardCrimeModel implements CrimeModel {
6 | private Crime crime;
7 |
8 | public StandardCrimeModel(Crime crime) {
9 | this.crime = crime;
10 | }
11 |
12 | @Override
13 | public Date getDate() {
14 | return crime.getDate();
15 | }
16 |
17 | @Override
18 | public void setTitle(String title) {
19 | crime.setTitle(title);
20 | }
21 |
22 | @Override
23 | public void setSolved(boolean solved) {
24 | crime.setSolved(solved);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crimes/CrimeListModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crimes;
2 |
3 | import com.olerass.pfexample.android.criminalintent.domain.crime.Crime;
4 |
5 | import java.util.List;
6 | import java.util.UUID;
7 |
8 | public interface CrimeListModel {
9 | List getCrimes();
10 | Crime getCrime(UUID uuid);
11 | }
12 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crimes/CrimeListPresenter.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crimes;
2 |
3 | import com.olerass.pfexample.android.criminalintent.domain.crime.Crime;
4 |
5 | public class CrimeListPresenter {
6 | private CrimeListView view;
7 | private CrimeListModel model;
8 |
9 | public CrimeListPresenter(CrimeListView view, CrimeListModel model) {
10 | this.view = view;
11 | this.model = model;
12 | initialize();
13 | }
14 |
15 | private void initialize() {
16 | view.setCrimes(model.getCrimes());
17 | view.whenCrimeSelected(uuid -> {
18 | Crime selected = model.getCrime(uuid);
19 | view.showCrimeMessage(selected.getTitle());
20 | });
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crimes/CrimeListView.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crimes;
2 |
3 | import com.olerass.pfexample.android.criminalintent.domain.crime.Crime;
4 | import com.olerass.pfexample.android.criminalintent.domain.event.DataEventListener;
5 |
6 | import java.util.List;
7 | import java.util.UUID;
8 |
9 | public interface CrimeListView {
10 | void setCrimes(List crimes);
11 | void showCrimeMessage(String crimeTitle);
12 |
13 | void whenCrimeSelected(DataEventListener listener);
14 | }
15 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/crimes/StandardCrimeListModel.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.crimes;
2 |
3 | import com.olerass.pfexample.android.criminalintent.domain.crime.Crime;
4 |
5 | import java.util.List;
6 | import java.util.UUID;
7 |
8 | public class StandardCrimeListModel implements CrimeListModel {
9 | private CrimeLab lab;
10 |
11 | public StandardCrimeListModel(CrimeLab lab) {
12 | this.lab = lab;
13 | }
14 |
15 | @Override
16 | public List getCrimes() {
17 | return lab.getCrimes();
18 | }
19 |
20 | @Override
21 | public Crime getCrime(UUID uuid) {
22 | return lab.getCrime(uuid);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/event/DataEvent.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.event;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class DataEvent {
7 | private List> listeners = new ArrayList<>();
8 |
9 | public void addListener(DataEventListener listener) {
10 | listeners.add(listener);
11 | }
12 |
13 | public void dispatch(T data) {
14 | for (DataEventListener listener : listeners) {
15 | listener.onDispatch(data);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/domain/event/DataEventListener.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.domain.event;
2 |
3 | public interface DataEventListener {
4 | void onDispatch(T data);
5 | }
6 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/platform/crime/CrimeActivity.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.platform.crime;
2 |
3 | import android.support.v4.app.Fragment;
4 |
5 | import com.olerass.pfexample.android.criminalintent.platform.SingleFragmentActivity;
6 |
7 | public class CrimeActivity extends SingleFragmentActivity {
8 | @Override
9 | protected Fragment createFragment() {
10 | return new CrimeFragment();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/java/com/olerass/pfexample/android/criminalintent/platform/crimes/CrimeListActivity.java:
--------------------------------------------------------------------------------
1 | package com.olerass.pfexample.android.criminalintent.platform.crimes;
2 |
3 | import android.support.v4.app.Fragment;
4 |
5 | import com.olerass.pfexample.android.criminalintent.platform.SingleFragmentActivity;
6 |
7 | public class CrimeListActivity extends SingleFragmentActivity {
8 | @Override
9 | protected Fragment createFragment() {
10 | return new CrimeListFragment();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/res/layout/activity_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/res/layout/fragment_crime_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter9-criminalintent/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter9-criminalintent/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter9-criminalintent/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter9-criminalintent/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter9-criminalintent/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | CriminalIntent
3 | Enter a title for the crime.
4 | Title
5 | Details
6 | Solved
7 |
8 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.5.0'
9 | classpath 'me.tatarka:gradle-retrolambda:3.2.4'
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/chapter9-criminalintent/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter9-criminalintent/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/chapter9-criminalintent/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
7 |
--------------------------------------------------------------------------------
/chapter9-criminalintent/screenshots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/olerass/presenter-first-android/c29bd6c905989540e582b00f0f031cee9d02505c/chapter9-criminalintent/screenshots.png
--------------------------------------------------------------------------------
/chapter9-criminalintent/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------