Skip to content

Commit

Permalink
Merge pull request #11 from andrzejchm/feature/custom-model-serializer
Browse files Browse the repository at this point in the history
Feature/custom model serializer
  • Loading branch information
andrzejchm committed Aug 10, 2016
2 parents 818a5e6 + 73a5801 commit 25438df
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 56 deletions.
10 changes: 10 additions & 0 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ test:
post:
- mkdir -p $CIRCLE_ARTIFACTS/sample/reports
- mkdir -p $CIRCLE_ARTIFACTS/sample/test-results
- mkdir -p $CIRCLE_ARTIFACTS/sample-dagger/reports
- mkdir -p $CIRCLE_ARTIFACTS/sample-dagger/test-results
- mkdir -p $CIRCLE_ARTIFACTS/library/reports
- mkdir -p $CIRCLE_ARTIFACTS/library/test-results
- cp -r sample/build/test-results/ $CIRCLE_ARTIFACTS/sample/test-results
- cp -r sample/build/reports/ $CIRCLE_ARTIFACTS/sample/reports
- cp -r sample/build/outputs/ $CIRCLE_ARTIFACTS/sample/outputs
- cp -r sample-dagger/build/test-results/ $CIRCLE_ARTIFACTS/sample-dagger/test-results
- cp -r sample-dagger/build/reports/ $CIRCLE_ARTIFACTS/sample-dagger/reports
- cp -r sample-dagger/build/outputs/ $CIRCLE_ARTIFACTS/sample-dagger/outputs
- cp -r library/build/test-results/ $CIRCLE_ARTIFACTS/library/test-results
- cp -r library/build/reports/ $CIRCLE_ARTIFACTS/library/reports
- cp -r library/build/outputs/ $CIRCLE_ARTIFACTS/library/outputs
2 changes: 1 addition & 1 deletion library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,6 @@ android {
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:24.0.0'
compile 'com.android.support:appcompat-v7:24.1.1'
compile 'com.google.code.findbugs:annotations:2.0.3'
}
30 changes: 21 additions & 9 deletions library/src/main/java/io/appflate/droidmvp/DroidMVPActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,20 @@
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import java.io.Serializable;

public abstract class DroidMVPActivity<M, V extends DroidMVPView, P extends DroidMVPPresenter<V, M>>
extends AppCompatActivity implements DroidMVPView {

private DroidMVPViewDelegate<M, V, P> mvpDelegate = new DroidMVPViewDelegate<M, V, P>() {
@NonNull @Override protected P createPresenter() {
return DroidMVPActivity.this.createPresenter();
}
private DroidMVPViewDelegate<M, V, P> mvpDelegate =
new DroidMVPViewDelegate<M, V, P>(createPresentationModelSerializer()) {
@NonNull @Override protected P createPresenter() {
return DroidMVPActivity.this.createPresenter();
}

@NonNull @Override protected M createPresentationModel() {
return DroidMVPActivity.this.createPresentationModel();
}
};
@NonNull @Override protected M createPresentationModel() {
return DroidMVPActivity.this.createPresentationModel();
}
};

@Override protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Expand Down Expand Up @@ -65,6 +65,18 @@ public abstract class DroidMVPActivity<M, V extends DroidMVPView, P extends Droi
return mvpDelegate.getPresenter();
}

/**
* Feel free to override this method that returns your own implementation of
* PresentationModelSerializer.
* Useful if you use a Parceler library for example
*
* @return an instance of PresentationModelSerializer that will serialize and deserialize your
* PresentationModel from Bundle.
*/
protected PresentationModelSerializer<M> createPresentationModelSerializer() {
return new ParcelableAndSerializablePresentationModelSerializer<>();
}

/**
* Used for performing field injection trough various dependency injection frameworks like
* Dagger. The injection is performed just before the #createPresenter() or
Expand Down
29 changes: 21 additions & 8 deletions library/src/main/java/io/appflate/droidmvp/DroidMVPFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,16 @@
public abstract class DroidMVPFragment<M, V extends DroidMVPView, P extends DroidMVPPresenter<V, M>>
extends Fragment implements DroidMVPView {

private DroidMVPViewDelegate<M, V, P> mvpDelegate = new DroidMVPViewDelegate<M, V, P>() {
@NonNull @Override protected P createPresenter() {
return DroidMVPFragment.this.createPresenter();
}
private DroidMVPViewDelegate<M, V, P> mvpDelegate =
new DroidMVPViewDelegate<M, V, P>(createPresentationModelSerializer()) {
@NonNull @Override protected P createPresenter() {
return DroidMVPFragment.this.createPresenter();
}

@NonNull @Override protected M createPresentationModel() {
return DroidMVPFragment.this.createPresentationModel();
}
};
@NonNull @Override protected M createPresentationModel() {
return DroidMVPFragment.this.createPresentationModel();
}
};

@Override public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Expand Down Expand Up @@ -60,6 +61,18 @@ public abstract class DroidMVPFragment<M, V extends DroidMVPView, P extends Droi
mvpDelegate.onDestroy();
}

/**
* Feel free to override this method that returns your own implementation of
* PresentationModelSerializer.
* Useful if you use a Parceler library for example
*
* @return an instance of PresentationModelSerializer that will serialize and deserialize your
* PresentationModel from Bundle.
*/
protected PresentationModelSerializer<M> createPresentationModelSerializer() {
return new ParcelableAndSerializablePresentationModelSerializer<>();
}

@NonNull protected P getPresenter() {
return mvpDelegate.getPresenter();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@
package io.appflate.droidmvp;

import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.Serializable;

/**
* Class that makes it possible to write your own custom MVP Views that will fit in the DroidMVP
Expand All @@ -36,9 +34,14 @@ public abstract class DroidMVPViewDelegate<M, V extends DroidMVPView, P extends

private P presenter;
private M presentationModel;
private final PresentationModelSerializer<M> serializer;

private String presentationModelKey;

public DroidMVPViewDelegate(@NonNull PresentationModelSerializer<M> serializer) {
this.serializer = serializer;
}

/**
* Commonly called from fragment's/activity's onCreate. Presentation Model is either created or
* restored
Expand All @@ -50,7 +53,8 @@ public abstract class DroidMVPViewDelegate<M, V extends DroidMVPView, P extends
*/
public void onCreate(DroidMVPView mvpView, @Nullable Bundle savedInstanceState) {
presentationModelKey = mvpView.getClass().getCanonicalName() + "$PresentationModel";
presentationModel = restorePresentationModel(savedInstanceState);
presentationModel =
serializer.restorePresentationModel(savedInstanceState, presentationModelKey);
if (presentationModel == null) {
presentationModel = createPresentationModel();
}
Expand Down Expand Up @@ -95,15 +99,7 @@ public void onCreate(DroidMVPView mvpView, @Nullable Bundle savedInstanceState)
*/
@SuppressFBWarnings("UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR") public void onSaveInstanceState(
Bundle outState) {
if (presentationModel instanceof Parcelable) {
outState.putParcelable(presentationModelKey, (Parcelable) presentationModel);
} else if (presentationModel instanceof Serializable) {
outState.putSerializable(presentationModelKey, (Serializable) presentationModel);
} else {
throw new IllegalArgumentException(
"Your presentation model must either implement Parcelable or Serializable interface: "
+ presentationModel.getClass().getCanonicalName());
}
serializer.savePresentationModel(outState, presentationModelKey, presentationModel);
}

public P getPresenter() {
Expand All @@ -127,18 +123,4 @@ private void checkPresentationModel() {
"seems like you forgot to create presentationModel in #createPresentationModel() method, or call the #onCreate() of this delegate");
}
}

private M restorePresentationModel(@Nullable Bundle savedInstanceState) {
if (savedInstanceState != null) {
Object potentialPresentationModel = savedInstanceState.get(presentationModelKey);
try {
return (M) potentialPresentationModel;
} catch (ClassCastException ex) {
throw new IllegalStateException(String.format(
"We expected a presentationModel saved in the bundle under the key: \"%s\", but was: %s",
presentationModelKey, potentialPresentationModel.toString()));
}
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package io.appflate.droidmvp;

import android.os.Bundle;
import android.os.Parcelable;
import java.io.Serializable;

/**
* Created by andrzejchm on 10/08/16.
*/
public class ParcelableAndSerializablePresentationModelSerializer<M>
implements PresentationModelSerializer<M> {
public M restorePresentationModel(Bundle savedInstanceState, String presentationModelKey) {
if (savedInstanceState != null) {
Object potentialPresentationModel = savedInstanceState.get(presentationModelKey);
try {
return (M) potentialPresentationModel;
} catch (ClassCastException ex) {
throw new IllegalStateException(String.format(
"We expected a presentationModel saved in the bundle under the key: \"%s\", but was: %s",
presentationModelKey,
potentialPresentationModel.toString()));
}
}
return null;
}

@Override public void savePresentationModel(Bundle outState, String presentationModelKey,
M presentationModel) {
if (presentationModel instanceof Parcelable) {
outState.putParcelable(presentationModelKey, (Parcelable) presentationModel);
} else if (presentationModel instanceof Serializable) {
outState.putSerializable(presentationModelKey, (Serializable) presentationModel);
} else {
throw new IllegalArgumentException(
"Your presentation model must either implement Parcelable or Serializable interface: "
+ presentationModel.getClass().getCanonicalName());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.appflate.droidmvp;

import android.os.Bundle;

/**
* Objects of this class are used to serialize and deserialize PresentationModel to/from the Bundle object.
*/
public interface PresentationModelSerializer<M> {
M restorePresentationModel(Bundle savedInstanceState, String presentationModelKey);

void savePresentationModel(Bundle outState, String presentationModelKey, M presentationModel);
}
8 changes: 4 additions & 4 deletions sample-dagger/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ android {

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:24.0.0'
compile 'com.android.support:design:24.0.0'
compile 'com.android.support:appcompat-v7:24.1.1'
compile 'com.android.support:design:24.1.1'
compile 'com.jakewharton:butterknife:7.0.1'
compile 'com.google.dagger:dagger:2.2'
compile 'com.squareup.retrofit2:retrofit:2.0.2'
Expand All @@ -73,8 +73,8 @@ dependencies {

//Test dependencies

testCompile 'com.android.support:appcompat-v7:24.0.0'
testCompile 'com.android.support:design:24.0.0'
testCompile 'com.android.support:appcompat-v7:24.1.1'
testCompile 'com.android.support:design:24.1.1'
testCompile 'junit:junit:4.12'
testCompile "org.robolectric:robolectric:3.0"
testCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
Expand Down
8 changes: 4 additions & 4 deletions sample-parcelable/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ android {

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:24.0.0'
compile 'com.android.support:design:24.0.0'
compile 'com.android.support:appcompat-v7:24.1.1'
compile 'com.android.support:design:24.1.1'
compile 'com.jakewharton:butterknife:7.0.1'
compile 'com.google.dagger:dagger:2.2'
compile 'com.squareup.retrofit2:retrofit:2.0.2'
Expand All @@ -73,8 +73,8 @@ dependencies {

//Test dependencies

testCompile 'com.android.support:appcompat-v7:24.0.0'
testCompile 'com.android.support:design:24.0.0'
testCompile 'com.android.support:appcompat-v7:24.1.1'
testCompile 'com.android.support:design:24.1.1'
testCompile 'junit:junit:4.12'
testCompile "org.robolectric:robolectric:3.0"
testCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
Expand Down
8 changes: 4 additions & 4 deletions sample/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ android {

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:24.0.0'
compile 'com.android.support:design:24.0.0'
compile 'com.android.support:appcompat-v7:24.1.1'
compile 'com.android.support:design:24.1.1'
compile 'com.jakewharton:butterknife:7.0.1'
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
Expand All @@ -70,8 +70,8 @@ dependencies {

//Test dependencies

testCompile 'com.android.support:appcompat-v7:24.0.0'
testCompile 'com.android.support:design:24.0.0'
testCompile 'com.android.support:appcompat-v7:24.1.1'
testCompile 'com.android.support:design:24.1.1'
testCompile 'junit:junit:4.12'
testCompile "org.robolectric:robolectric:3.0"
testCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
Expand Down

0 comments on commit 25438df

Please sign in to comment.