Skip to content

Commit 62cb8d4

Browse files
author
Daniel Novak
authored
Merge pull request #31 from inloop/get_view_optional
Add getViewOptional method - NonNull getView variant
2 parents 8163599 + 8d07534 commit 62cb8d4

File tree

6 files changed

+104
-9
lines changed

6 files changed

+104
-9
lines changed

library/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ apply plugin: 'maven'
33

44
android {
55
compileSdkVersion 25
6-
buildToolsVersion '24.0.3'
6+
buildToolsVersion '25.0.2'
77

88
defaultConfig {
99
minSdkVersion 15
@@ -25,7 +25,7 @@ android {
2525
}
2626

2727
dependencies {
28-
compile 'com.android.support:appcompat-v7:25.1.0'
28+
compile 'com.android.support:appcompat-v7:25.1.1'
2929
}
3030

3131
task androidJavadocs(type: Javadoc) {

library/src/main/java/eu/inloop/viewmodel/AbstractViewModel.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import android.content.Intent;
55
import android.os.Bundle;
66
import android.support.annotation.CallSuper;
7+
import android.support.annotation.CheckResult;
78
import android.support.annotation.NonNull;
89
import android.support.annotation.Nullable;
910
import android.support.v4.app.Fragment;
@@ -18,8 +19,15 @@ public abstract class AbstractViewModel<T extends IView> {
1819
@Nullable
1920
private T mView;
2021

22+
@Nullable
23+
private final Class<?> mClassType;
24+
2125
private boolean mBindViewWasCalled;
2226

27+
public AbstractViewModel() {
28+
mClassType = ProxyViewHelper.getGenericType(getClass(), IView.class);
29+
}
30+
2331
void setUniqueIdentifier(@NonNull final String uniqueIdentifier) {
2432
mUniqueIdentifier = uniqueIdentifier;
2533
}
@@ -59,11 +67,25 @@ public void onBindView(@NonNull T view) {
5967
mView = view;
6068
}
6169

70+
@CheckResult
6271
@Nullable
6372
public T getView() {
6473
return mView;
6574
}
6675

76+
@CheckResult
77+
@NonNull
78+
public T getViewOptional() {
79+
if (mView != null) {
80+
return mView;
81+
} else {
82+
if (mClassType == null) {
83+
throw new IllegalStateException("Your view must implement IView");
84+
}
85+
return ProxyViewHelper.init(mClassType);
86+
}
87+
}
88+
6789
@CallSuper
6890
public void clearView() {
6991
mView = null;
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package eu.inloop.viewmodel;
2+
3+
4+
import android.support.annotation.NonNull;
5+
import android.support.annotation.Nullable;
6+
7+
import java.lang.reflect.InvocationHandler;
8+
import java.lang.reflect.Method;
9+
import java.lang.reflect.ParameterizedType;
10+
import java.lang.reflect.Proxy;
11+
import java.lang.reflect.Type;
12+
13+
public class ProxyViewHelper {
14+
15+
private static final class ProxyDummyClass {
16+
}
17+
18+
private static final ProxyDummyClass sDummyClass = new ProxyDummyClass();
19+
private static final Class[] sInterfaces = new Class[1];
20+
21+
private ProxyViewHelper() {
22+
}
23+
24+
@SuppressWarnings("unchecked")
25+
@NonNull
26+
static <T> T init(@NonNull Class<?> in) {
27+
sInterfaces[0] = in;
28+
return (T) Proxy.newProxyInstance(sDummyClass.getClass().getClassLoader(), sInterfaces, sInvocationHandler);
29+
}
30+
31+
@Nullable
32+
public static Class<?> getGenericType(@NonNull Class<?> in, @NonNull Class<?> whichExtends) {
33+
final Type genericSuperclass = in.getGenericSuperclass();
34+
if (genericSuperclass instanceof ParameterizedType) {
35+
final Type[] typeArgs = ((ParameterizedType) genericSuperclass).getActualTypeArguments();
36+
for (Type arg : typeArgs) {
37+
final Class<?> argClass = (Class<?>) arg;
38+
if (whichExtends.isAssignableFrom(argClass)) {
39+
return argClass;
40+
}
41+
}
42+
}
43+
return null;
44+
}
45+
46+
private static final InvocationHandler sInvocationHandler = new InvocationHandler() {
47+
@Override
48+
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
49+
return null;
50+
}
51+
};
52+
53+
}

library/src/main/java/eu/inloop/viewmodel/base/ViewModelBaseActivity.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import eu.inloop.viewmodel.AbstractViewModel;
99
import eu.inloop.viewmodel.IView;
10+
import eu.inloop.viewmodel.ProxyViewHelper;
1011
import eu.inloop.viewmodel.ViewModelHelper;
1112
import eu.inloop.viewmodel.binding.ViewModelBindingConfig;
1213

@@ -19,7 +20,14 @@ public abstract class ViewModelBaseActivity<T extends IView, R extends AbstractV
1920
@Override
2021
protected void onCreate(@Nullable final Bundle savedInstanceState) {
2122
super.onCreate(savedInstanceState);
22-
mViewModeHelper.onCreate(this, savedInstanceState, getViewModelClass(), getIntent().getExtras());
23+
24+
Class<? extends AbstractViewModel<T>> viewModelClass = getViewModelClass();
25+
// try to extract the ViewModel class from the implementation
26+
if (viewModelClass == null) {
27+
//noinspection unchecked
28+
viewModelClass = (Class<? extends AbstractViewModel<T>>) ProxyViewHelper.getGenericType(getClass(), AbstractViewModel.class);
29+
}
30+
mViewModeHelper.onCreate(this, savedInstanceState, viewModelClass, getIntent().getExtras());
2331
}
2432

2533
/**
@@ -32,7 +40,9 @@ public void setModelView(@NonNull final T view) {
3240
}
3341

3442
@Nullable
35-
public abstract Class<R> getViewModelClass();
43+
public Class<R> getViewModelClass() {
44+
return null;
45+
}
3646

3747
@CallSuper
3848
@Override

library/src/main/java/eu/inloop/viewmodel/base/ViewModelBaseFragment.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import eu.inloop.viewmodel.AbstractViewModel;
1111
import eu.inloop.viewmodel.IView;
12+
import eu.inloop.viewmodel.ProxyViewHelper;
1213
import eu.inloop.viewmodel.ViewModelHelper;
1314
import eu.inloop.viewmodel.binding.ViewModelBindingConfig;
1415

@@ -21,7 +22,14 @@ public abstract class ViewModelBaseFragment<T extends IView, R extends AbstractV
2122
@Override
2223
public void onCreate(@Nullable final Bundle savedInstanceState) {
2324
super.onCreate(savedInstanceState);
24-
getViewModelHelper().onCreate(getActivity(), savedInstanceState, getViewModelClass(), getArguments());
25+
26+
Class<? extends AbstractViewModel<T>> viewModelClass = getViewModelClass();
27+
// try to extract the ViewModel class from the implementation
28+
if (viewModelClass == null) {
29+
//noinspection unchecked
30+
viewModelClass = (Class<? extends AbstractViewModel<T>>) ProxyViewHelper.getGenericType(getClass(), AbstractViewModel.class);
31+
}
32+
getViewModelHelper().onCreate(getActivity(), savedInstanceState, viewModelClass, getArguments());
2533
}
2634

2735
@CallSuper
@@ -60,7 +68,9 @@ public void onDestroy() {
6068
}
6169

6270
@Nullable
63-
public abstract Class<R> getViewModelClass();
71+
public Class<R> getViewModelClass() {
72+
return null;
73+
}
6474

6575
/**
6676
* @see ViewModelHelper#getViewModel()

sample/build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ apply plugin: 'com.android.application'
22

33
android {
44
compileSdkVersion 24
5-
buildToolsVersion '24.0.2'
5+
buildToolsVersion '25.0.2'
66

77
defaultConfig {
88
applicationId 'eu.inloop.viewmodel.sample'
99
minSdkVersion 15
10-
targetSdkVersion 24
10+
targetSdkVersion 25
1111
versionCode 1
1212
versionName '1.0'
1313
}
@@ -30,7 +30,7 @@ android {
3030
}
3131

3232
dependencies {
33-
compile 'com.android.support:appcompat-v7:24.2.1'
33+
compile 'com.android.support:appcompat-v7:25.1.1'
3434
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4'
3535
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4'
3636
compile 'com.jakewharton:butterknife:5.1.2'

0 commit comments

Comments
 (0)