├── MvvmSample
├── .classpath
├── .gitignore
├── .project
├── AndroidManifest.xml
├── libs
│ ├── android-support-v4.jar
│ └── jackson-all-1.9.9.jar
├── proguard-project.txt
├── project.properties
├── res
│ ├── drawable-hdpi
│ │ └── ic_launcher.png
│ ├── drawable-mdpi
│ │ └── ic_launcher.png
│ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ ├── drawable
│ │ ├── video_pause.png
│ │ ├── video_pause_drawable.xml
│ │ ├── video_pause_pressed.png
│ │ ├── video_play.png
│ │ ├── video_play_drawable.xml
│ │ └── video_play_pressed.png
│ ├── layout
│ │ └── activity_main.xml
│ ├── menu
│ │ └── activity_main.xml
│ ├── values-v11
│ │ └── styles.xml
│ ├── values-v14
│ │ └── styles.xml
│ └── values
│ │ ├── strings.xml
│ │ └── styles.xml
└── src
│ └── com
│ └── example
│ └── mvvmsample
│ ├── model
│ ├── Video.java
│ └── state
│ │ └── VideoPlayerState.java
│ ├── mvvm
│ ├── BaseStateModel.java
│ ├── BaseViewModel.java
│ ├── BaseViewModelEvent.java
│ ├── Event.java
│ └── Observable.java
│ ├── view
│ └── VideoPlayerView.java
│ └── viewmodel
│ ├── VideoPlayerViewModel.java
│ └── VideoPlayerViewModelEvent.java
└── README.md
/MvvmSample/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/MvvmSample/.gitignore:
--------------------------------------------------------------------------------
1 | /bin
2 | /gen
3 |
--------------------------------------------------------------------------------
/MvvmSample/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | MvvmSample
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/MvvmSample/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/MvvmSample/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kejunxia/Android-Mvvm/4cd52427d1462435d96da4fee0c9a8987c00b50b/MvvmSample/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/MvvmSample/libs/jackson-all-1.9.9.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kejunxia/Android-Mvvm/4cd52427d1462435d96da4fee0c9a8987c00b50b/MvvmSample/libs/jackson-all-1.9.9.jar
--------------------------------------------------------------------------------
/MvvmSample/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/MvvmSample/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-17
15 |
--------------------------------------------------------------------------------
/MvvmSample/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kejunxia/Android-Mvvm/4cd52427d1462435d96da4fee0c9a8987c00b50b/MvvmSample/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/MvvmSample/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kejunxia/Android-Mvvm/4cd52427d1462435d96da4fee0c9a8987c00b50b/MvvmSample/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/MvvmSample/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kejunxia/Android-Mvvm/4cd52427d1462435d96da4fee0c9a8987c00b50b/MvvmSample/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/MvvmSample/res/drawable/video_pause.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kejunxia/Android-Mvvm/4cd52427d1462435d96da4fee0c9a8987c00b50b/MvvmSample/res/drawable/video_pause.png
--------------------------------------------------------------------------------
/MvvmSample/res/drawable/video_pause_drawable.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/MvvmSample/res/drawable/video_pause_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kejunxia/Android-Mvvm/4cd52427d1462435d96da4fee0c9a8987c00b50b/MvvmSample/res/drawable/video_pause_pressed.png
--------------------------------------------------------------------------------
/MvvmSample/res/drawable/video_play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kejunxia/Android-Mvvm/4cd52427d1462435d96da4fee0c9a8987c00b50b/MvvmSample/res/drawable/video_play.png
--------------------------------------------------------------------------------
/MvvmSample/res/drawable/video_play_drawable.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/MvvmSample/res/drawable/video_play_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kejunxia/Android-Mvvm/4cd52427d1462435d96da4fee0c9a8987c00b50b/MvvmSample/res/drawable/video_play_pressed.png
--------------------------------------------------------------------------------
/MvvmSample/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
16 |
17 |
26 |
27 |
35 |
36 |
44 |
45 |
53 |
54 |
62 |
63 |
--------------------------------------------------------------------------------
/MvvmSample/res/menu/activity_main.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/MvvmSample/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/MvvmSample/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/MvvmSample/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | MvvmSample
5 | Hello world!
6 | Settings
7 |
8 |
--------------------------------------------------------------------------------
/MvvmSample/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
--------------------------------------------------------------------------------
/MvvmSample/src/com/example/mvvmsample/model/Video.java:
--------------------------------------------------------------------------------
1 | package com.example.mvvmsample.model;
2 |
3 | public class Video {
4 | private String mName;
5 | private int Duration;
6 |
7 | /**
8 | * @return the name
9 | */
10 | public String getName() {
11 | return mName;
12 | }
13 |
14 | /**
15 | * @param name
16 | * the name to set
17 | */
18 | public void setName(String name) {
19 | mName = name;
20 | }
21 |
22 | /**
23 | * @return the duration
24 | */
25 | public int getDuration() {
26 | return Duration;
27 | }
28 |
29 | /**
30 | * @param duration
31 | * the duration to set
32 | */
33 | public void setDuration(int duration) {
34 | Duration = duration;
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/MvvmSample/src/com/example/mvvmsample/model/state/VideoPlayerState.java:
--------------------------------------------------------------------------------
1 | package com.example.mvvmsample.model.state;
2 |
3 | import com.example.mvvmsample.model.Video;
4 | import com.example.mvvmsample.mvvm.BaseStateModel;
5 |
6 | public class VideoPlayerState extends BaseStateModel {
7 | // ViewModel State Model contains a data model
8 | private Video mCurrentVideo;
9 | private boolean mPlaying;
10 |
11 | /**
12 | * @return the currentVideo
13 | */
14 | public Video getCurrentVideo() {
15 | return mCurrentVideo;
16 | }
17 |
18 | /**
19 | * @param currentVideo
20 | * the currentVideo to set
21 | */
22 | public void setCurrentVideo(Video currentVideo) {
23 | mCurrentVideo = currentVideo;
24 | }
25 |
26 | /**
27 | * @return the playing
28 | */
29 | public boolean isPlaying() {
30 | return mPlaying;
31 | }
32 |
33 | /**
34 | * @param playing
35 | * the playing to set
36 | */
37 | public void setPlaying(boolean playing) {
38 | mPlaying = playing;
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/MvvmSample/src/com/example/mvvmsample/mvvm/BaseStateModel.java:
--------------------------------------------------------------------------------
1 | package com.example.mvvmsample.mvvm;
2 |
3 | /**
4 | * Model to incorporate with viewmodels. State models are used to persist and
5 | * restore the state of view models(so the views associated with the view
6 | * models).
7 | *
8 | * @author Chris
9 | *
10 | */
11 | public class BaseStateModel {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/MvvmSample/src/com/example/mvvmsample/mvvm/BaseViewModel.java:
--------------------------------------------------------------------------------
1 | package com.example.mvvmsample.mvvm;
2 |
3 | public abstract class BaseViewModel, MODEL extends BaseStateModel>
4 | extends Observable {
5 | protected MODEL mModel;
6 |
7 | /**
8 | * Model is persistable data that keeps the state of the view model so can
9 | * be used to initialize the view model.
10 | *
11 | * @return the model
12 | */
13 | public MODEL getModel() {
14 | return mModel;
15 | }
16 |
17 | /**
18 | * Model is persistable data that keeps the state of the view model so can
19 | * be used to initialize the view model.
20 | *
21 | * Binding a data model should update all sub-views to reflect the data. To
22 | * To update specific data and a sub-view, create more methods to do so in
23 | * derived classes.
24 | *
25 | *
26 | * @param dataModel
27 | */
28 | public void bindData(MODEL dataModel) {
29 | mModel = dataModel;
30 | for (BaseViewModelEvent event : this) {
31 | event.onDataBound(dataModel);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/MvvmSample/src/com/example/mvvmsample/mvvm/BaseViewModelEvent.java:
--------------------------------------------------------------------------------
1 | package com.example.mvvmsample.mvvm;
2 |
3 | public interface BaseViewModelEvent extends Event {
4 | void onDataBound(MODEL dataModel);
5 | }
6 |
--------------------------------------------------------------------------------
/MvvmSample/src/com/example/mvvmsample/mvvm/Event.java:
--------------------------------------------------------------------------------
1 | package com.example.mvvmsample.mvvm;
2 |
3 | public interface Event {}
4 |
--------------------------------------------------------------------------------
/MvvmSample/src/com/example/mvvmsample/mvvm/Observable.java:
--------------------------------------------------------------------------------
1 | package com.example.mvvmsample.mvvm;
2 |
3 | import java.util.Iterator;
4 | import java.util.concurrent.ConcurrentLinkedQueue;
5 |
6 | public abstract class Observable implements Iterable {
7 | private final ConcurrentLinkedQueue mEvents;
8 |
9 | public Observable() {
10 | mEvents = new ConcurrentLinkedQueue();
11 | }
12 |
13 | /**
14 | * Register an event
15 | *
16 | * @param event
17 | */
18 | public void registerEvent(T event) {
19 | mEvents.add(event);
20 | }
21 |
22 | /**
23 | * Unregister an event
24 | *
25 | * @param event
26 | */
27 | public void unregisterEvent(T event) {
28 | mEvents.remove(event);
29 | }
30 |
31 | /**
32 | * Clear all events
33 | */
34 | public void clearEvents() {
35 | mEvents.clear();
36 | }
37 |
38 | @Override
39 | public Iterator iterator() {
40 | return mEvents.iterator();
41 | }
42 |
43 | public int getEventCount() {
44 | return mEvents.size();
45 | }
46 | }
--------------------------------------------------------------------------------
/MvvmSample/src/com/example/mvvmsample/view/VideoPlayerView.java:
--------------------------------------------------------------------------------
1 | package com.example.mvvmsample.view;
2 |
3 | import java.io.IOException;
4 |
5 | import org.codehaus.jackson.map.ObjectMapper;
6 |
7 | import android.app.Activity;
8 | import android.os.Bundle;
9 | import android.util.Log;
10 | import android.view.View;
11 | import android.view.View.OnClickListener;
12 | import android.widget.Button;
13 | import android.widget.ImageView;
14 | import android.widget.TextView;
15 | import android.widget.Toast;
16 |
17 | import com.example.mvvmsample.R;
18 | import com.example.mvvmsample.model.Video;
19 | import com.example.mvvmsample.model.state.VideoPlayerState;
20 | import com.example.mvvmsample.viewmodel.VideoPlayerViewModel;
21 | import com.example.mvvmsample.viewmodel.VideoPlayerViewModelEvent;
22 |
23 | public class VideoPlayerView extends Activity implements OnClickListener {
24 | private static ObjectMapper sMapper;
25 | private static final String KEY_STATE_JSON = "KeyStateJson";
26 |
27 | private static final String TAG = VideoPlayerView.class.getSimpleName();
28 | private TextView mTextPlayingVideo;
29 | private TextView mTextVideoLen;
30 | private ImageView mPlayingButton;
31 | private Button mBtnLoadVideo;
32 | private VideoPlayerViewModel mViewModel;
33 | private VideoPlayerViewModelEvent mEvent;
34 |
35 | private VideoPlayerState mVideoPlayerState;
36 |
37 | @Override
38 | protected void onCreate(Bundle savedInstanceState) {
39 | super.onCreate(savedInstanceState);
40 | setContentView(R.layout.activity_main);
41 |
42 | mPlayingButton = (ImageView) findViewById(R.id.imgPlayerButton);
43 | mPlayingButton.setOnClickListener(this);
44 | mTextPlayingVideo = (TextView) findViewById(R.id.txtPlayingVideoTitle);
45 | mTextVideoLen = (TextView) findViewById(R.id.txtVideoLength);
46 | mTextPlayingVideo.setOnClickListener(this);
47 | mBtnLoadVideo = (Button) findViewById(R.id.btnLoadVideo);
48 | mBtnLoadVideo.setOnClickListener(this);
49 |
50 | mViewModel = new VideoPlayerViewModel();
51 |
52 | // Setup events handler for the view models
53 | mEvent = new VideoPlayerViewModelEvent() {
54 | @Override
55 | public void onDataBound(VideoPlayerState dataModel) {
56 | if (dataModel == null) {
57 | mTextPlayingVideo.setText("No Video");
58 | mTextVideoLen.setText("0s");
59 | mPlayingButton.setImageResource(R.drawable.video_play_drawable);
60 | mBtnLoadVideo.setText("Load Video");
61 | } else {
62 | if (dataModel.getCurrentVideo() != null) {
63 | mTextPlayingVideo.setText(dataModel.getCurrentVideo().getName());
64 | mTextVideoLen.setText(dataModel.getCurrentVideo().getDuration() + "s");
65 | mPlayingButton.setImageResource(R.drawable.video_pause_drawable);
66 | }
67 | mBtnLoadVideo.setText("Unload Video");
68 | }
69 |
70 | }
71 |
72 | @Override
73 | public void onVideoPlayed(Video video) {
74 | mTextPlayingVideo.setText(video.getName());
75 | mPlayingButton.setImageResource(R.drawable.video_pause_drawable);
76 | Toast.makeText(getApplicationContext(), video.getName() + " is played.",
77 | Toast.LENGTH_SHORT).show();
78 | }
79 |
80 | @Override
81 | public void onVideoPaused(Video video) {
82 | mPlayingButton.setImageResource(R.drawable.video_play_drawable);
83 | Toast.makeText(getApplicationContext(), video.getName() + " is paused.",
84 | Toast.LENGTH_SHORT).show();
85 | }
86 | };
87 | // Register events.
88 | mViewModel.registerEvent(mEvent);
89 |
90 | // Use JSON to serialize state which is easy and quick, if too slow
91 | // replace it by Parcealable instead.
92 | if (savedInstanceState == null) {
93 | // Check if invoking activity send a video to play
94 | if (getIntent() != null) {
95 | if (getIntent().hasExtra(KEY_STATE_JSON)) {
96 | try {
97 | mVideoPlayerState = getMapper().readValue(
98 | getIntent().getStringExtra(KEY_STATE_JSON), VideoPlayerState.class);
99 | } catch (IOException e) {
100 | Log.e(TAG, e.getMessage(), e);
101 | }
102 | }
103 | }
104 | } else {
105 | // Restore the instance state when
106 | // 1. rotating the phone,
107 | // 2. back from background when it's killed by OS
108 |
109 | // This can be done in a base class for all view
110 | if (savedInstanceState.containsKey(KEY_STATE_JSON)) {
111 | try {
112 | mVideoPlayerState = getMapper().readValue(
113 | savedInstanceState.getString(KEY_STATE_JSON), VideoPlayerState.class);
114 | mViewModel.bindData(mVideoPlayerState);
115 | } catch (IOException e) {
116 | Log.e(TAG, e.getMessage(), e);
117 | }
118 | }
119 | }
120 | // No pre set player state, create a new one for testing.
121 | if (mVideoPlayerState == null) {
122 | mVideoPlayerState = new VideoPlayerState();
123 | Video video = new Video();
124 | video.setName("Test Video");
125 | video.setDuration(90);
126 | mVideoPlayerState.setCurrentVideo(video);
127 | }
128 | }
129 |
130 | // Remember to save instance state. Using static is dangerous as Android OS
131 | // will clear it in background. If you rely on them, you will find they
132 | // suddenly turned null when app came back from the background after a long
133 | // time period.
134 |
135 | // This can be done in a base class for all view
136 | @Override
137 | protected void onSaveInstanceState(Bundle outState) {
138 | super.onSaveInstanceState(outState);
139 | if (mViewModel.getModel() != null) {
140 | try {
141 | outState.putString(KEY_STATE_JSON,
142 | getMapper().writeValueAsString(mViewModel.getModel()));
143 | } catch (IOException e) {
144 | Log.e(TAG, e.getMessage(), e);
145 | }
146 | }
147 | }
148 |
149 | @Override
150 | public void onClick(View view) {
151 | switch (view.getId()) {
152 | case R.id.btnLoadVideo:
153 | // Load unload button clicked.
154 | if (mViewModel.getModel() == null) {
155 | mViewModel.bindData(mVideoPlayerState);
156 | } else {
157 | mViewModel.bindData(null);
158 | }
159 | break;
160 | case R.id.imgPlayerButton:
161 | // Play/Pause button clicked.
162 | VideoPlayerState m = mViewModel.getModel();
163 | if (m != null) {
164 | if (!m.isPlaying()) {
165 | mViewModel.playVideo();
166 | } else {
167 | mViewModel.pauseVideo();
168 | }
169 | } else {
170 | mViewModel.bindData(mVideoPlayerState);
171 | mViewModel.playVideo();
172 | }
173 | break;
174 | default:
175 | break; // do nothing
176 | }
177 | }
178 |
179 | private static ObjectMapper getMapper() {
180 | if (sMapper == null) {
181 | sMapper = new ObjectMapper();
182 | }
183 | return sMapper;
184 | }
185 | }
186 |
--------------------------------------------------------------------------------
/MvvmSample/src/com/example/mvvmsample/viewmodel/VideoPlayerViewModel.java:
--------------------------------------------------------------------------------
1 | package com.example.mvvmsample.viewmodel;
2 |
3 | import com.example.mvvmsample.model.state.VideoPlayerState;
4 | import com.example.mvvmsample.mvvm.BaseViewModel;
5 |
6 | public class VideoPlayerViewModel extends
7 | BaseViewModel {
8 |
9 | public void playVideo() {
10 | if (mModel != null) {
11 | if (!mModel.isPlaying()) {
12 | mModel.setPlaying(true);
13 | for (VideoPlayerViewModelEvent evet : this) {
14 | evet.onVideoPlayed(mModel.getCurrentVideo());
15 | }
16 | }
17 | }
18 | }
19 |
20 | public void pauseVideo() {
21 | if (mModel != null) {
22 | if (mModel.isPlaying()) {
23 | mModel.setPlaying(false);
24 | for (VideoPlayerViewModelEvent evet : this) {
25 | evet.onVideoPaused(mModel.getCurrentVideo());
26 | }
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/MvvmSample/src/com/example/mvvmsample/viewmodel/VideoPlayerViewModelEvent.java:
--------------------------------------------------------------------------------
1 | package com.example.mvvmsample.viewmodel;
2 |
3 | import com.example.mvvmsample.model.Video;
4 | import com.example.mvvmsample.model.state.VideoPlayerState;
5 | import com.example.mvvmsample.mvvm.BaseViewModelEvent;
6 |
7 | public interface VideoPlayerViewModelEvent extends BaseViewModelEvent {
8 | void onVideoPlayed(Video video);
9 |
10 | void onVideoPaused(Video video);
11 | }
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ###This project is deprecated.
2 |
3 | ###Please see [Android MVC Framework on Github](https://github.com/kejunxia/AndroidMvc)
4 |
5 | ###And its Websit
6 | [http://kejunxia.github.io/AndroidMvc/](http://kejunxia.github.io/AndroidMvc/)
7 |
--------------------------------------------------------------------------------