Commit 376cc3d9 authored by Keiko Katsuragawa's avatar Keiko Katsuragawa
Browse files

add MVC examples

parent e949b5f0
.idea
.idea/
# Created by https://www.gitignore.io/api/androidstudio
### AndroidStudio ###
# Covers files to be ignored for android development using Android Studio.
# Built application files
*.apk
*.ap_
# Files for the ART/Dalvik VM
*.dex
# Java class files
*.class
# Generated files
bin/
gen/
out/
# Gradle files
.gradle
.gradle/
build/
# Signing files
.signing/
# Local configuration file (sdk path, etc)
local.properties
# Proguard folder generated by Eclipse
proguard/
# Log Files
*.log
# Android Studio
/*/build/
/*/local.properties
/*/out
/*/*/build
/*/*/production
captures/
.navigation/
*.ipr
*~
*.swp
# Android Patch
gen-external-apklibs
# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild
# NDK
obj/
# IntelliJ IDEA
*.iml
*.iws
/out/
# User-specific configurations
.idea/libraries/
.idea/workspace.xml
.idea/tasks.xml
.idea/.name
.idea/compiler.xml
.idea/copyright/profiles_settings.xml
.idea/encodings.xml
.idea/misc.xml
.idea/modules.xml
.idea/scopes/scope_settings.xml
.idea/dictionaries
.idea/vcs.xml
.idea/jsLibraryMappings.xml
.idea/datasources.xml
.idea/dataSources.ids
.idea/sqlDataSources.xml
.idea/dynamic.xml
.idea/uiDesigner.xml
# OS-specific files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# Legacy Eclipse project files
.classpath
.project
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.war
*.ear
# virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml)
hs_err_pid*
## Plugin-specific files:
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Mongo Explorer plugin
.idea/mongoSettings.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### AndroidStudio Patch ###
!/gradle/wrapper/gradle-wrapper.jar
# End of https://www.gitignore.io/api/androidstudio
\ No newline at end of file
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "cs349.uwaterloo.ca.mvc1"
minSdkVersion 23
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
package cs349.uwaterloo.ca.mvc1;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest
{
@Test
public void useAppContext() throws Exception
{
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("cs349.uwaterloo.ca.mvc1", appContext.getPackageName());
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest package="cs349.uwaterloo.ca.mvc1"
xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
\ No newline at end of file
package cs349.uwaterloo.ca.mvc1;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.ViewGroup;
public class MainActivity extends AppCompatActivity
{
// Private Vars
Model model;
/**
* OnCreate
* -- Called when application is initially launched.
* @see <a href="https://developer.android.com/guide/components/activities/activity-lifecycle.html">Android LifeCycle</a>
* @param savedInstanceState
*/
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Log.d(String.valueOf(R.string.DEBUG_MVC_ID), "onCreate called");
// Load base UI layout from resources.
setContentView(R.layout.activity_main);
// Init Model
model = new Model();
////////////////////////////////////////
// Setup Views
////////////////////////////////////////
View1 view1 = new View1(this, model);
ViewGroup v1 = (ViewGroup) findViewById(R.id.mainactivity_1);
v1.addView(view1);
View2 view2 = new View2(this, model);
ViewGroup v2 = (ViewGroup) findViewById(R.id.mainactivity_2);
v2.addView(view2);
// Init Views
model.initObservers();
}
////////////////////////////////////////////////////////////////////////////////////////////////
//
// Save and Restore State
//
////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Save the state of the application
* @param outState
*/
@Override
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
Log.d(String.valueOf(R.string.DEBUG_MVC_ID), "MainActivity: Save model state.");
// Serialize all sateful values form model
outState.putInt("Counter", model.getCounter());
}
/**
* This method is called after {@link #onStart} when the activity is
* being re-initialized from a previously saved state, given here in
* <var>savedInstanceState</var>. Most implementations will simply use {@link #onCreate}
* to restore their state, but it is sometimes convenient to do it here
* after all of the initialization has been done or to allow subclasses to
* decide whether to use your default implementation. The default
* implementation of this method performs a restore of any view state that
* had previously been frozen by {@link #onSaveInstanceState}.
* <p>
* <p>This method is called between {@link #onStart} and
* {@link #onPostCreate}.
*
* @param savedInstanceState the data most recently supplied in {@link #onSaveInstanceState}.
* @see #onCreate
* @see #onPostCreate
* @see #onResume
* @see #onSaveInstanceState
*/
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState)
{
super.onRestoreInstanceState(savedInstanceState);
Log.d(String.valueOf(R.string.DEBUG_MVC_ID), "MainActivity: Restore model");
// Get all values and restore them to model
model.setCounter(savedInstanceState.getInt("Counter"));
}
}
package cs349.uwaterloo.ca.mvc1;
import android.util.Log;
import java.util.Observable;
import java.util.Observer;
/**
* CS349_AndroidSamples
* <p>
* Created by J. J. Hartmann on 11/19/2017.
* Email: j3hartma@uwaterloo.ca
* Copyright 2017
*/
/**
* Class Model
* - Stores a persistent state for the application.
*/
public class Model extends Observable
{
// Private Variables
private int mCounter;
/**
* Model Constructor:
* - Init member variables
*/
Model() {
mCounter = 0;
}
/**
* Get mCounter Values
* @return Current value mCounter
*/
public int getCounter()
{
return mCounter;
}
/**
* Set mCounter Value
* @param i
* -- Value to set Counter
*/
public void setCounter(int i)
{
Log.d("DEMO", "Model: set counter to " + mCounter);
this.mCounter = i;
}
/**
* Increment mCounter by 1
*/
public void incrementCounter()
{
mCounter++;
Log.d("DEMO", "Model: increment counter to " + mCounter);
// Observable API
setChanged();
notifyObservers();
}
////////////////////////////////////////////////////////////////////////////////////////////////
//
// Observable Methods
//
////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Helper method to make it easier to initialize all observers
*/
public void initObservers()
{
setChanged();
notifyObservers();
}
/**
* Deletes an observer from the set of observers of this object.
* Passing <CODE>null</CODE> to this method will have no effect.
*
* @param o the observer to be deleted.
*/
@Override
public synchronized void deleteObserver(Observer o)
{
super.deleteObserver(o);
}
/**
* Adds an observer to the set of observers for this object, provided
* that it is not the same as some observer already in the set.
* The order in which notifications will be delivered to multiple
* observers is not specified. See the class comment.
*
* @param o an observer to be added.
* @throws NullPointerException if the parameter o is null.
*/
@Override
public synchronized void addObserver(Observer o)
{
super.addObserver(o);
}
/**
* Clears the observer list so that this object no longer has any observers.
*/
@Override
public synchronized void deleteObservers()
{
super.deleteObservers();
}
/**
* If this object has changed, as indicated by the
* <code>hasChanged</code> method, then notify all of its observers
* and then call the <code>clearChanged</code> method to
* indicate that this object has no longer changed.
* <p>
* Each observer has its <code>update</code> method called with two
* arguments: this observable object and <code>null</code>. In other
* words, this method is equivalent to:
* <blockquote><tt>
* notifyObservers(null)</tt></blockquote>
*
* @see Observable#clearChanged()
* @see Observable#hasChanged()
* @see Observer#update(Observable, Object)
*/
@Override
public void notifyObservers()
{
super.notifyObservers();
}
}
package cs349.uwaterloo.ca.mvc1;
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import java.util.Observable;
import java.util.Observer;
/**
* CS349_AndroidSamples
* <p>
* Created by J. J. Hartmann on 11/19/2017.
* Email: j3hartma@uwaterloo.ca
* Copyright 2017
*/
public class View1 extends LinearLayout implements Observer
{
// Private Vars
private Model model;
private Button button;
public View1(Context context, Model m)
{
super(context);
Log.d(String.valueOf(R.string.DEBUG_MVC_ID), "View1: Constructor");
// Get the XML view description and "inflate" it into the display (like rendering)
View.inflate(context, R.layout.view1_layout, this);
// Save model
model = m;
// Add view to observer
model.addObserver(this);
// Get reference for button
button = (Button) findViewById(R.id.view1_button);
// Create controller for button
button.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
// Increment model when button is clicked
model.incrementCounter();
}
});
}
/**
* This method is called whenever the observed object is changed. An
* application calls an <tt>Observable</tt> object's
* <code>notifyObservers</code> method to have all the object's
* observers notified of the change.
*
* @param o the observable object.
* @param arg an argument passed to the <code>notifyObservers</code>
*/
@Override
public void update(Observable o, Object arg)
{
Log.d(String.valueOf(R.string.DEBUG_MVC_ID), "View1: Update Called");
// Update button text the click count from model
button.setText(String.valueOf(model.getCounter()));
}
}
package cs349.uwaterloo.ca.mvc1;
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.Observable;
import java.util.Observer;
/**
* CS349_AndroidSamples
* <p>
* Created by J. J. Hartmann on 11/19/2017.
* Email: j3hartma@uwaterloo.ca
* Copyright 2017
*/
public class View2 extends LinearLayout implements Observer
{
// Private Vars
private Model model;
private TextView textView;
public View2(Context context, Model m)
{
super(context);
Log.d(String.valueOf(R.string.DEBUG_MVC_ID), "View2: Constructor Called");
// Get the XML view description and "inflate" it into the display (like rendering)
View.inflate(context, R.layout.view2_layout, this);
// Save model ref
this.model = m;
// Add view to model list of observers
model.addObserver(this);
// get reference to widgets and manipulate updates
textView = (TextView) findViewById(R.id.view2_textView);
// Create a controller to increment counter when clicked
textView.setOnClickListener(new OnClickListener()