User to decide which class to load Android - android

EDIT: I'll try and make it clearer sorry for the confusion.
I have two livewallpapers one is called the Past one is called the Future, what I want to do is put both into one livewallpaper (sort of a two for one deal) but let the user decide which one they want to load.
How I had it set up for one (let's say the Past) I had the onDraw method running in a class called the Past (it did not impliment anything) just past the onDraw and put the whole livewallpaper togeather.
In the livewallpaper engine I had this.
public class ThePastActivity extends WallpaperService {
#Override
public Engine onCreateEngine() {
return new ThePastActivityEngine();
}
class ThePastActivityEngine extends Engine {
private Past _past;
public ThePastActivityEngine() {
this._past = new Past();
this._past.initialize(getBaseContext(), getSurfaceHolder());
}
#Override
public void onVisibilityChanged(boolean visible) {
if(visible){
this._past.render();
}
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
}
#Override
public void onSurfaceCreated(SurfaceHolder holder) {
super.onSurfaceCreated(holder);
this._past.start();
}
#Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
super.onSurfaceDestroyed(holder);
this._past.stop();
}
#Override
public void onOffsetsChanged(float xOffset, float yOffset,float xStep, float yStep, int xPixels, int yPixels) {
this._past.drawXOff = Math.round((this._blimp.theBackgroundImage.getWidth() - initFrameParamsWidth()) * -xOffset);
this._past.drawYOff = Math.round((this._blimp.theBackgroundImage.getHeight() - initFrameParams()) * -yOffset);
this._past.render();
}
}
Now I have two instead of one. The new one is called Future so now I have it like so:
public class ThePastActivity extends WallpaperService {
public static final String SHARED_PREFS_NAME = "livewallpapersettings";
public static final String PREFERENCE_BACK = "livewallpaper_back";
#Override
public Engine onCreateEngine() {
return new ThePastActivityEngine();
}
class ThePastActivityEngine extends Engine implements SharedPreferences.OnSharedPreferenceChangeListener{
private SharedPreferences prefs;
private String whichEra;
private Past _past;
private Future _future;
//make a new name ChooseEra and let it become either Past or Future
private ChooseEra _chooseEra;
public ThePastActivityEngine() {
this._chooseEra = new ChooseEra();
this._past.initialize(getBaseContext(), getSurfaceHolder());
prefs = TheSteampunkCityActivity.this.getSharedPreferences(SHARED_PREFS_NAME, 0);
prefs.registerOnSharedPreferenceChangeListener(this);
onSharedPreferenceChanged(prefs, null);
}
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
whichEra=(prefs.getString(PREFERENCE_BACK, "past"));
// from here I want to get either the "past" or "future"
// make the ChooseEra to be either Past or Future
// and use that for this livewallpaper engine instead
}
#Override
public void onVisibilityChanged(boolean visible) {
if(visible){
this._chooseEra.render();
}
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
}
#Override
public void onSurfaceCreated(SurfaceHolder holder) {
super.onSurfaceCreated(holder);
this._past.start();
}
#Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
super.onSurfaceDestroyed(holder);
this._chooseEra.stop();
}
#Override
public void onOffsetsChanged(float xOffset, float yOffset,float xStep, float yStep, int xPixels, int yPixels) {
this._chooseEra.drawXOff = Math.round((this._chooseEra.theBackgroundImage.getWidth() - initFrameParamsWidth()) * -xOffset);
this._chooseEra.drawYOff = Math.round((this._chooseEra.theBackgroundImage.getHeight() - initFrameParams()) * -yOffset);
this._chooseEra.render();
}
}
So chooseEra has to become either Future or Past so it reads one of the two classes only and passes the arguments along through the engine.
The issue I am having is making ChooseEra to become either Past or Future. Normally using a method is easy to do but this is the first time I am trying to make it change the class name so when I put
private ChooseEra _chooseEra;
it makes no sense at all, I tried ChooseEra = Past and ChooseEra = Future in an if else statement comparing the prefs of "past" and "future" but no luck.
Again any help is greatly appreciated.
Sam

Your having typing issues. If you want to return the implementation to use (either Future or Past) then they need a shared interface or base class that you can use. I'll pick the name to be Era. Define all of your variables of that shared type and it will work. For example:
public Era readTheEra(SharedPreferences prefs) {
String whichEra = prefs.getString(PREFERENCE_BACK, "past");
Era era = whichEra.equals("past") ? new Past() : new Future();
return era;
}
Notice Era is marked as the return type of the method (you had void which won't work). Also notice I simply passed the SharedPreferences to the method, and encapsulated the code to extract the preference value in the method. That way you aren't writing to instance variables (that you don't need), then reading in other methods. Just pass the information to the method, and don't save the intermediate steps. The only thing you need is the Era reference to use. The value of the preference isn't needed after you instantiate the correct class.
You'll need to mark the two concrete implementations as implementing the Era Interface:
public interface Era {
// put methods here you need both implementations to
// have so you can work from Era interface and not the
// individual concrete clases.
}
public class Past implements Era {
...
}
public class Future implements Era {
...
}
public class Engine {
private Era era;
...
private Era readTheEra(SharedPreferences prefs) {
String whichEra = prefs.getString(PREFERENCE_BACK, "past");
Era era = whichEra.equals("past") ? new Past() : new Future();
return era;
}
}
I picked to use Interfaces because your question isn't clear enough to know if you need classes or can use simply Interfaces. But all of the same thing applies if you need to use some class like Activity or whatever. Subclass Activty with an abstract base class, and Past and Future should subclass the abstract base class.

Related

Is it possible to skip onPause() method of BaseActivity in MainActivity when latter extends former? [duplicate]

I read this question and thought that would easily be solved (not that it isn't solvable without) if one could write:
#Override
public String toString() {
return super.super.toString();
}
I'm not sure if it is useful in many cases, but I wonder why it isn't and if something like this exists in other languages.
What do you guys think?
EDIT:
To clarify: yes I know, that's impossible in Java and I don't really miss it. This is nothing I expected to work and was surprised getting a compiler error. I just had the idea and like to discuss it.
It violates encapsulation. You shouldn't be able to bypass the parent class's behaviour. It makes sense to sometimes be able to bypass your own class's behaviour (particularly from within the same method) but not your parent's. For example, suppose we have a base "collection of items", a subclass representing "a collection of red items" and a subclass of that representing "a collection of big red items". It makes sense to have:
public class Items
{
public void add(Item item) { ... }
}
public class RedItems extends Items
{
#Override
public void add(Item item)
{
if (!item.isRed())
{
throw new NotRedItemException();
}
super.add(item);
}
}
public class BigRedItems extends RedItems
{
#Override
public void add(Item item)
{
if (!item.isBig())
{
throw new NotBigItemException();
}
super.add(item);
}
}
That's fine - RedItems can always be confident that the items it contains are all red. Now suppose we were able to call super.super.add():
public class NaughtyItems extends RedItems
{
#Override
public void add(Item item)
{
// I don't care if it's red or not. Take that, RedItems!
super.super.add(item);
}
}
Now we could add whatever we like, and the invariant in RedItems is broken.
Does that make sense?
I think Jon Skeet has the correct answer. I'd just like to add that you can access shadowed variables from superclasses of superclasses by casting this:
interface I { int x = 0; }
class T1 implements I { int x = 1; }
class T2 extends T1 { int x = 2; }
class T3 extends T2 {
int x = 3;
void test() {
System.out.println("x=\t\t" + x);
System.out.println("super.x=\t\t" + super.x);
System.out.println("((T2)this).x=\t" + ((T2)this).x);
System.out.println("((T1)this).x=\t" + ((T1)this).x);
System.out.println("((I)this).x=\t" + ((I)this).x);
}
}
class Test {
public static void main(String[] args) {
new T3().test();
}
}
which produces the output:
x= 3
super.x= 2
((T2)this).x= 2
((T1)this).x= 1
((I)this).x= 0
(example from the JLS)
However, this doesn't work for method calls because method calls are determined based on the runtime type of the object.
I think the following code allow to use super.super...super.method() in most case.
(even if it's uggly to do that)
In short
create temporary instance of ancestor type
copy values of fields from original object to temporary one
invoke target method on temporary object
copy modified values back to original object
Usage :
public class A {
public void doThat() { ... }
}
public class B extends A {
public void doThat() { /* don't call super.doThat() */ }
}
public class C extends B {
public void doThat() {
Magic.exec(A.class, this, "doThat");
}
}
public class Magic {
public static <Type, ChieldType extends Type> void exec(Class<Type> oneSuperType, ChieldType instance,
String methodOfParentToExec) {
try {
Type type = oneSuperType.newInstance();
shareVars(oneSuperType, instance, type);
oneSuperType.getMethod(methodOfParentToExec).invoke(type);
shareVars(oneSuperType, type, instance);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static <Type, SourceType extends Type, TargetType extends Type> void shareVars(Class<Type> clazz,
SourceType source, TargetType target) throws IllegalArgumentException, IllegalAccessException {
Class<?> loop = clazz;
do {
for (Field f : loop.getDeclaredFields()) {
if (!f.isAccessible()) {
f.setAccessible(true);
}
f.set(target, f.get(source));
}
loop = loop.getSuperclass();
} while (loop != Object.class);
}
}
I don't have enough reputation to comment so I will add this to the other answers.
Jon Skeet answers excellently, with a beautiful example. Matt B has a point: not all superclasses have supers. Your code would break if you called a super of a super that had no super.
Object oriented programming (which Java is) is all about objects, not functions. If you want task oriented programming, choose C++ or something else. If your object doesn't fit in it's super class, then you need to add it to the "grandparent class", create a new class, or find another super it does fit into.
Personally, I have found this limitation to be one of Java's greatest strengths. Code is somewhat rigid compared to other languages I've used, but I always know what to expect. This helps with the "simple and familiar" goal of Java. In my mind, calling super.super is not simple or familiar. Perhaps the developers felt the same?
There's some good reasons to do this. You might have a subclass which has a method which is implemented incorrectly, but the parent method is implemented correctly. Because it belongs to a third party library, you might be unable/unwilling to change the source. In this case, you want to create a subclass but override one method to call the super.super method.
As shown by some other posters, it is possible to do this through reflection, but it should be possible to do something like
(SuperSuperClass this).theMethod();
I'm dealing with this problem right now - the quick fix is to copy and paste the superclass method into the subsubclass method :)
In addition to the very good points that others have made, I think there's another reason: what if the superclass does not have a superclass?
Since every class naturally extends (at least) Object, super.whatever() will always refer to a method in the superclass. But what if your class only extends Object - what would super.super refer to then? How should that behavior be handled - a compiler error, a NullPointer, etc?
I think the primary reason why this is not allowed is that it violates encapsulation, but this might be a small reason too.
I think if you overwrite a method and want to all the super-class version of it (like, say for equals), then you virtually always want to call the direct superclass version first, which one will call its superclass version in turn if it wants.
I think it only makes rarely sense (if at all. i can't think of a case where it does) to call some arbitrary superclass' version of a method. I don't know if that is possible at all in Java. It can be done in C++:
this->ReallyTheBase::foo();
At a guess, because it's not used that often. The only reason I could see using it is if your direct parent has overridden some functionality and you're trying to restore it back to the original.
Which seems to me to be against OO principles, since the class's direct parent should be more closely related to your class than the grandparent is.
Calling of super.super.method() make sense when you can't change code of base class. This often happens when you are extending an existing library.
Ask yourself first, why are you extending that class? If answer is "because I can't change it" then you can create exact package and class in your application, and rewrite naughty method or create delegate:
package com.company.application;
public class OneYouWantExtend extends OneThatContainsDesiredMethod {
// one way is to rewrite method() to call super.method() only or
// to doStuff() and then call super.method()
public void method() {
if (isDoStuff()) {
// do stuff
}
super.method();
}
protected abstract boolean isDoStuff();
// second way is to define methodDelegate() that will call hidden super.method()
public void methodDelegate() {
super.method();
}
...
}
public class OneThatContainsDesiredMethod {
public void method() {...}
...
}
For instance, you can create org.springframework.test.context.junit4.SpringJUnit4ClassRunner class in your application so this class should be loaded before the real one from jar. Then rewrite methods or constructors.
Attention: This is absolute hack, and it is highly NOT recommended to use but it's WORKING! Using of this approach is dangerous because of possible issues with class loaders. Also this may cause issues each time you will update library that contains overwritten class.
#Jon Skeet Nice explanation.
IMO if some one wants to call super.super method then one must be want to ignore the behavior of immediate parent, but want to access the grand parent behavior.
This can be achieved through instance Of. As below code
public class A {
protected void printClass() {
System.out.println("In A Class");
}
}
public class B extends A {
#Override
protected void printClass() {
if (!(this instanceof C)) {
System.out.println("In B Class");
}
super.printClass();
}
}
public class C extends B {
#Override
protected void printClass() {
System.out.println("In C Class");
super.printClass();
}
}
Here is driver class,
public class Driver {
public static void main(String[] args) {
C c = new C();
c.printClass();
}
}
Output of this will be
In C Class
In A Class
Class B printClass behavior will be ignored in this case.
I am not sure about is this a ideal or good practice to achieve super.super, but still it is working.
Look at this Github project, especially the objectHandle variable. This project shows how to actually and accurately call the grandparent method on a grandchild.
Just in case the link gets broken, here is the code:
import lombok.val;
import org.junit.Assert;
import org.junit.Test;
import java.lang.invoke.*;
/*
Your scientists were so preoccupied with whether or not they could, they didn’t stop to think if they should.
Please don't actually do this... :P
*/
public class ImplLookupTest {
private MethodHandles.Lookup getImplLookup() throws NoSuchFieldException, IllegalAccessException {
val field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
field.setAccessible(true);
return (MethodHandles.Lookup) field.get(null);
}
#Test
public void test() throws Throwable {
val lookup = getImplLookup();
val baseHandle = lookup.findSpecial(Base.class, "toString",
MethodType.methodType(String.class),
Sub.class);
val objectHandle = lookup.findSpecial(Object.class, "toString",
MethodType.methodType(String.class),
// Must use Base.class here for this reference to call Object's toString
Base.class);
val sub = new Sub();
Assert.assertEquals("Sub", sub.toString());
Assert.assertEquals("Base", baseHandle.invoke(sub));
Assert.assertEquals(toString(sub), objectHandle.invoke(sub));
}
private static String toString(Object o) {
return o.getClass().getName() + "#" + Integer.toHexString(o.hashCode());
}
public class Sub extends Base {
#Override
public String toString() {
return "Sub";
}
}
public class Base {
#Override
public String toString() {
return "Base";
}
}
}
Happy Coding!!!!
I would put the super.super method body in another method, if possible
class SuperSuperClass {
public String toString() {
return DescribeMe();
}
protected String DescribeMe() {
return "I am super super";
}
}
class SuperClass extends SuperSuperClass {
public String toString() {
return "I am super";
}
}
class ChildClass extends SuperClass {
public String toString() {
return DescribeMe();
}
}
Or if you cannot change the super-super class, you can try this:
class SuperSuperClass {
public String toString() {
return "I am super super";
}
}
class SuperClass extends SuperSuperClass {
public String toString() {
return DescribeMe(super.toString());
}
protected String DescribeMe(string fromSuper) {
return "I am super";
}
}
class ChildClass extends SuperClass {
protected String DescribeMe(string fromSuper) {
return fromSuper;
}
}
In both cases, the
new ChildClass().toString();
results to "I am super super"
It would seem to be possible to at least get the class of the superclass's superclass, though not necessarily the instance of it, using reflection; if this might be useful, please consider the Javadoc at http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getSuperclass()
public class A {
#Override
public String toString() {
return "A";
}
}
public class B extends A {
#Override
public String toString() {
return "B";
}
}
public class C extends B {
#Override
public String toString() {
return "C";
}
}
public class D extends C {
#Override
public String toString() {
String result = "";
try {
result = this.getClass().getSuperclass().getSuperclass().getSuperclass().newInstance().toString();
} catch (InstantiationException ex) {
Logger.getLogger(D.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(D.class.getName()).log(Level.SEVERE, null, ex);
}
return result;
}
}
public class Main {
public static void main(String... args) {
D d = new D();
System.out.println(d);
}
}
run:
A
BUILD SUCCESSFUL (total time: 0 seconds)
I have had situations like these when the architecture is to build common functionality in a common CustomBaseClass which implements on behalf of several derived classes.
However, we need to circumvent common logic for specific method for a specific derived class. In such cases, we must use a super.super.methodX implementation.
We achieve this by introducing a boolean member in the CustomBaseClass, which can be used to selectively defer custom implementation and yield to default framework implementation where desirable.
...
FrameworkBaseClass (....) extends...
{
methodA(...){...}
methodB(...){...}
...
methodX(...)
...
methodN(...){...}
}
/* CustomBaseClass overrides default framework functionality for benefit of several derived classes.*/
CustomBaseClass(...) extends FrameworkBaseClass
{
private boolean skipMethodX=false;
/* implement accessors isSkipMethodX() and setSkipMethodX(boolean)*/
methodA(...){...}
methodB(...){...}
...
methodN(...){...}
methodX(...){
if (isSkipMethodX()) {
setSKipMethodX(false);
super.methodX(...);
return;
}
... //common method logic
}
}
DerivedClass1(...) extends CustomBaseClass
DerivedClass2(...) extends CustomBaseClass
...
DerivedClassN(...) extends CustomBaseClass...
DerivedClassX(...) extends CustomBaseClass...
{
methodX(...){
super.setSKipMethodX(true);
super.methodX(...);
}
}
However, with good architecture principles followed in framework as well as app, we could avoid such situations easily, by using hasA approach, instead of isA approach. But at all times it is not very practical to expect well designed architecture in place, and hence the need to get away from solid design principles and introduce hacks like this.
Just my 2 cents...
IMO, it's a clean way to achieve super.super.sayYourName() behavior in Java.
public class GrandMa {
public void sayYourName(){
System.out.println("Grandma Fedora");
}
}
public class Mama extends GrandMa {
public void sayYourName(boolean lie){
if(lie){
super.sayYourName();
}else {
System.out.println("Mama Stephanida");
}
}
}
public class Daughter extends Mama {
public void sayYourName(boolean lie){
if(lie){
super.sayYourName(lie);
}else {
System.out.println("Little girl Masha");
}
}
}
public class TestDaughter {
public static void main(String[] args){
Daughter d = new Daughter();
System.out.print("Request to lie: d.sayYourName(true) returns ");
d.sayYourName(true);
System.out.print("Request not to lie: d.sayYourName(false) returns ");
d.sayYourName(false);
}
}
Output:
Request to lie: d.sayYourName(true) returns Grandma Fedora
Request not to lie: d.sayYourName(false) returns Little girl Masha
I think this is a problem that breaks the inheritance agreement.
By extending a class you obey / agree its behavior, features
Whilst when calling super.super.method(), you want to break your own obedience agreement.
You just cannot cherry pick from the super class.
However, there may happen situations when you feel the need to call super.super.method() - usually a bad design sign, in your code or in the code you inherit !
If the super and super super classes cannot be refactored (some legacy code), then opt for composition over inheritance.
Encapsulation breaking is when you #Override some methods by breaking the encapsulated code.
The methods designed not to be overridden are marked
final.
In C# you can call a method of any ancestor like this:
public class A
internal virtual void foo()
...
public class B : A
public new void foo()
...
public class C : B
public new void foo() {
(this as A).foo();
}
Also you can do this in Delphi:
type
A=class
procedure foo;
...
B=class(A)
procedure foo; override;
...
C=class(B)
procedure foo; override;
...
A(objC).foo();
But in Java you can do such focus only by some gear. One possible way is:
class A {
int y=10;
void foo(Class X) throws Exception {
if(X!=A.class)
throw new Exception("Incorrect parameter of "+this.getClass().getName()+".foo("+X.getName()+")");
y++;
System.out.printf("A.foo(%s): y=%d\n",X.getName(),y);
}
void foo() throws Exception {
System.out.printf("A.foo()\n");
this.foo(this.getClass());
}
}
class B extends A {
int y=20;
#Override
void foo(Class X) throws Exception {
if(X==B.class) {
y++;
System.out.printf("B.foo(%s): y=%d\n",X.getName(),y);
} else {
System.out.printf("B.foo(%s) calls B.super.foo(%s)\n",X.getName(),X.getName());
super.foo(X);
}
}
}
class C extends B {
int y=30;
#Override
void foo(Class X) throws Exception {
if(X==C.class) {
y++;
System.out.printf("C.foo(%s): y=%d\n",X.getName(),y);
} else {
System.out.printf("C.foo(%s) calls C.super.foo(%s)\n",X.getName(),X.getName());
super.foo(X);
}
}
void DoIt() {
try {
System.out.printf("DoIt: foo():\n");
foo();
Show();
System.out.printf("DoIt: foo(B):\n");
foo(B.class);
Show();
System.out.printf("DoIt: foo(A):\n");
foo(A.class);
Show();
} catch(Exception e) {
//...
}
}
void Show() {
System.out.printf("Show: A.y=%d, B.y=%d, C.y=%d\n\n", ((A)this).y, ((B)this).y, ((C)this).y);
}
}
objC.DoIt() result output:
DoIt: foo():
A.foo()
C.foo(C): y=31
Show: A.y=10, B.y=20, C.y=31
DoIt: foo(B):
C.foo(B) calls C.super.foo(B)
B.foo(B): y=21
Show: A.y=10, B.y=21, C.y=31
DoIt: foo(A):
C.foo(A) calls C.super.foo(A)
B.foo(A) calls B.super.foo(A)
A.foo(A): y=11
Show: A.y=11, B.y=21, C.y=31
It is simply easy to do. For instance:
C subclass of B and B subclass of A. Both of three have method methodName() for example.
public abstract class A {
public void methodName() {
System.out.println("Class A");
}
}
public class B extends A {
public void methodName() {
super.methodName();
System.out.println("Class B");
}
// Will call the super methodName
public void hackSuper() {
super.methodName();
}
}
public class C extends B {
public static void main(String[] args) {
A a = new C();
a.methodName();
}
#Override
public void methodName() {
/*super.methodName();*/
hackSuper();
System.out.println("Class C");
}
}
Run class C Output will be:
Class A
Class C
Instead of output:
Class A
Class B
Class C
If you think you are going to be needing the superclass, you could reference it in a variable for that class. For example:
public class Foo
{
public int getNumber()
{
return 0;
}
}
public class SuperFoo extends Foo
{
public static Foo superClass = new Foo();
public int getNumber()
{
return 1;
}
}
public class UltraFoo extends Foo
{
public static void main(String[] args)
{
System.out.println(new UltraFoo.getNumber());
System.out.println(new SuperFoo().getNumber());
System.out.println(new SuperFoo().superClass.getNumber());
}
public int getNumber()
{
return 2;
}
}
Should print out:
2
1
0
public class SubSubClass extends SubClass {
#Override
public void print() {
super.superPrint();
}
public static void main(String[] args) {
new SubSubClass().print();
}
}
class SuperClass {
public void print() {
System.out.println("Printed in the GrandDad");
}
}
class SubClass extends SuperClass {
public void superPrint() {
super.print();
}
}
Output: Printed in the GrandDad
The keyword super is just a way to invoke the method in the superclass.
In the Java tutorial:https://docs.oracle.com/javase/tutorial/java/IandI/super.html
If your method overrides one of its superclass's methods, you can invoke the overridden method through the use of the keyword super.
Don't believe that it's a reference of the super object!!! No, it's just a keyword to invoke methods in the superclass.
Here is an example:
class Animal {
public void doSth() {
System.out.println(this); // It's a Cat! Not an animal!
System.out.println("Animal do sth.");
}
}
class Cat extends Animal {
public void doSth() {
System.out.println(this);
System.out.println("Cat do sth.");
super.doSth();
}
}
When you call cat.doSth(), the method doSth() in class Animal will print this and it is a cat.

Is my implementation pattern for MVP valid?

I'm new to Android and MVP in-general, and I've been doing iOS programming for the last 1.5 years, so I find delegate patterns easy to digest. I've implemented MVP in such a way that the view conforms to a presenter's protocol, which lets the presenter disregard the view's specific type, but lets it know that certain methods are a given and thus okay to call on the "view." I've been reading various MVP guides, and all of the Mosby tutorials, and I'm not sure I agree with some of it. Is the pattern I've implemented kosher? I'd like some feedback so I don't keep heading in a bad direction, if that is indeed what I'm doing...
For example,
Base Presenter:
public abstract class Presenter<V, S> implements BasePresenterInterface<V, S> {
public interface PresenterProtocol extends BasePresenterProtocol {
}
private WeakReference<V> mAttachedView = null;
private S mService = null;
/**
* Interface Overrides
*/
#Override
public void attachView(V view) {
boolean viewDoesNotConform = !viewDoesConform(view);
if (viewDoesNotConform) {
Log.d("DEBUG", "Cannot attach View that does not conform to PresenterProtocol");
return;
}
mAttachedView = new WeakReference<>(view);
((BasePresenterProtocol) getAttachedView()).onViewAttached();
}
#Override
public void detachView() {
mAttachedView = null;
}
#Override
public boolean viewDoesConform(V view) {
Class<?> klass = view.getClass();
boolean conforms = BasePresenterInterface.BasePresenterProtocol.class.isAssignableFrom(klass);
return conforms;
}
#Override
public boolean viewIsAttached() {
return mAttachedView != null;
}
#Override
public V getAttachedView() {
return mAttachedView.get();
}
#Override
public S getService() {
return mService;
}
#Override
public void setService(S service) {
mService = service;
}
}
I then subclass this into the following:
PhotoRecyclerPresenter:
public class PhotoRecyclerPresenter extends Presenter<PhotoRecyclerPresenter.PhotoRecyclerPresenterProtocol, PhotoService> {
public interface PhotoRecyclerPresenterProtocol extends Presenter.PresenterProtocol {
void onPhotosLoaded(List<TestPhoto> photoList);
void onItemSelected(TestPhoto photo);
void onShowDetail(TestPhoto photo);
}
private static PhotoRecyclerPresenter mSharedInstance;
private PhotoRecyclerPresenter() {
setService(new PhotoService());
}
/**
* External Methods
*/
public void getPhotos() {
boolean noAttachedView = !viewIsAttached();
if (noAttachedView) {
Log.d("DEBUG", "No view attached");
return;
}
getService().getAPI()
.getPhotos()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(photoList -> getAttachedView().onPhotosLoaded(photoList));
}
/**
* Internal Methods
*/
public static PhotoRecyclerPresenter getSharedInstance() {
boolean firstInstance = mSharedInstance == null;
if (firstInstance) {
setSharedInstance(new PhotoRecyclerPresenter());
}
return mSharedInstance;
}
public static void setSharedInstance(PhotoRecyclerPresenter instance) {
mSharedInstance = instance;
}
public void didSelectItem(TestPhoto photo) {
getAttachedView().showDetail(photo);
}
}
And it communicates with the view:
PhotoRecyclerFragment:
public class PhotoRecyclerFragment extends Fragment implements PhotoRecyclerPresenter.PhotoRecyclerPresenterProtocol {
private RecyclerView mRecyclerView;
private RecyclerView.LayoutManager mLayoutManager;
private Activity mParentActivity;
private PhotoRecyclerPresenter mPresenter;
private PhotoRecyclerAdapter mAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_recycler, container, false);
mParentActivity = getActivity();
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
mLayoutManager = new LinearLayoutManager(mParentActivity);
mAdapter = new PhotoRecyclerAdapter(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
mPresenter = PhotoRecyclerPresenter.getSharedInstance();
mPresenter.attachView(this);
return rootView;
}
#Override
public void onDestroyView() {
super.onDestroyView();
mPresenter.detachView();
mAdapter.clear();
}
/**
* PhotoRecyclerPresenterProtocol Methods
*/
#Override
public void onItemSelected(TestPhoto photo) {
mPresenter.didSelectItem(photo);
}
#Override
public void onPhotosLoaded(List<TestPhoto> photoList) {
mAdapter.loadPhotos(photoList);
}
#Override
public void onViewAttached() {
mPresenter.getPhotos();
}
#Override
public void onViewDetached() {
}
#Override
public void onShowDetail(TestPhoto photo) {
Intent detailIntent = new Intent(mParentActivity, PhotoDetailActivity.class);
mParentActivity.startActivity(detailIntent.putExtra(Intent.EXTRA_UID, photo.getPhotoId()));
}
}
This lets me define a set of requirements a view needs to conform to in order to utilize the singleton presenter, while keeping the presenter agnostic about what views use it, as long as they conform to its protocol. So far in my practice project it seems to work fine, but I can't seem to find any resources where what I'm doing is recommended as far as MVP goes, and I have enough self-doubt that I figured I'd ask my first StackOverflow question. Can anyone who has experience with MVP shed some light on this?
Also, if I'm asking in the wrong place, feel free to point me to the correct place to post this.
Thanks :)
From my point of view you are doing the same thing that Mosby does. The only difference is the name of the interface (or protocol in objective-c) world. You call it PresenterProtocol while Mosby call it MvpView. Both are doing the same job: Offering the Presenter an Api of methods the presenter can call to manipulate the view.
The only thing that doesn't make sense is to have a method viewDoesConform(). In Java you have type safety. You can use the generics type V of your Presenter to ensure that your fragment is implementing the Presenter's protocol. just change it to V extends BasePresentersProtocol
Furthermore I think that it doesn't make sense to have a "shared instance" (a.k.a Singleton pattern) of the presenter. I think it would make more sense to have a "shared instance" of the PhotoService. But But please note also that by doing so your code is not testable (unit tests) anymore. You should google for Dependency injection or Inverse of Control to understand how to write modular, reusable and testable code. I'm not talking about dependency injection frameworks like Dagger , spring or guice. You just should understand the idea behind dependency injection. You can write classes following this principle completely without dependency injection frameworks (i.e. using constructor parameters).
Side note: you never unsubscribe your presenter from PhotoService. Depending on how PhotoService is implemented you may have a memory leak because PhotoService observable has a reference to the presenter which prevents the presenter and PhotoService (depending on your concrete implementation) from being garbage collected.
Edit: Mosby defines the protocol for the View. Have a look at the getting started section on the project website. The HelloWorldView defines two methods: showHello() and showGoodbye() (implented by the HelloWorldActivity) and HelloWorldPresenter calls these two methods to manipulate the View. The HelloWorldPresenter also cancels the async requests to avoid memory leaks. You should do that too. Otherwise your presenter can only be garbage collected after the retrofit httpcall has completed.

how to pass, from a class to another, the name of a variable (NOT the value)

I need to pass name of a variable created in Class A to the Class B, so I can put a value in that variable (in Class B).
But, in Class B I do not know the name of that variable.
The code is something like this:
Class A
public class A {
int valore; // this is the variable, in Class b, I don't know this name!
public void callClassB(){
ClassB.Method(what shoudld i put here?)
}
}
This is the Class B
public class B {
public void Method(the_Name_Of_TheVariable_I_get){
the_Name_Of_TheVariable_I_get = 5; // i need to do this
}
}
Why do you need the variable name? Simply pass the variable itself. In class B create a method
public int getValore(){
return valore;
}
Then in Class A use modify the code as
public void callClassB(){
ClassB.Method(getValore())
}
I do not really understand what you are trying to achieve here?
You can also use the following appraoch:
interface ValueSetter {
void setValue(int value);
}
Class A
public class A implements ValueSetter{
int valore;
public void callClassB(){
ClassB.Method(this)
}
void setValue(int value){
valore = value;
}
}
This is the class B
public class B{
public void Method(ValueSetter valueSetter){
ValueSetter.setValue(5);
}
}
This is more inline with OOPS..
You will need to use reflection for this.
Here is a tutorial from Oracle: http://docs.oracle.com/javase/tutorial/reflect/index.html
You cant get the name of variable at runtime though. But assuming you have the name of the field the code would look something like this:
this.getClass().getDeclaredField(the_Name_Of_TheVariable_I_get).set(this, 5);
you can pass the name of the variable "valore", then you need reflection to assign it in your method :
a = new A();
Field f = a.getClass().getDeclaredField(varName);
f.set(a, 5);
a can be a parameter too. (it is necessary to give the instance that possesses the member).
However, this is not a recommended way of treating your issue, as it is unreliable in the sense that the compiler will not be able to check you are accessing items that actually exist.
It would be better to use an interface, for instance :
public interface Settable {
public void set(int value);
}
and then:
public class A implements Settable {
private int valore;
public void set(int value) {
valore = value;
}
public void callClassB(){
ClassB.Method(this);
}
}
and in B:
public class B{
public void Method(Settable settable){
settable.set(5);
}
}

Android project local manually created lib

I am not sure I did the right thing. The main reason for my doubts is that I cannot find, in this or other forums, someone who has done a similar thing.
I created an abstract java class in my project. Named it lib. I put there several structures and methods used by all other classes in the project.
It works for me, but I want to know if there is a more accepted method of gathering all common methods and structures.
Note: All methods of course are declared as public static.
Note II: I did not know how to get the context within the abstract class, so if needed I had to pass it as argument to the method.
Is this wat you are looking for?
public abstract class AbstractActivity extends Activity{
public static synchronized boolean showAlertBox(Context ctx,final String title,final String message,final String okBtnTxt,final OnClickListener clickListener){
AlertDialog.Builder alertbox; alertbox = new AlertDialog.Builder(ctx);
this.runOnUiThread(new Runnable() {
#Override
public void run() {
alertbox.setTitle(title);
alertbox.setMessage(message);
if(okBtnTxt!=null || clickListener!=null)
alertbox.setNeutralButton(okBtnTxt,clickListener);
alertbox.show();
.....
}
});
return true;
}
}
In the class extending this abstract class you can just call it by using showAlertBox(this);
Other wise use AbstractActivity.showAlertBox(Context);
Well, thanks to #Matt Wolfe's comment I came to know that what I did is called "Utility class" and it is widely used to share common code in a project.
The general template is:
public abstract class lib {
public static final int ZERO = 0;
public static final int ONE = 1;
public static final int TWO = 2;
public static void func1(int i) {
}
public static void func2(int i, String s) {
}
}
and you can use it like this from any other code:
...;
lib.func1( lib.ZERO );
lib func2( lib.TWO, "sandwich" );
...;
Knowing that makes me confident that what I did is OK.
It would be perfect to find a way to avoid the prefix lib. and just have ECLIPSE, and the compiler, find the right import and recognize the function with just its name, like they do for global libraries.

How to use callbacks in my own code

Here I update my world to include the canvas size
world.getViewPort().updateViewPortSize(width,height);
Is there a better way to do this? Is there a way that I can automatically update my world object without having to manually call it in the setSurfaceSize method but instead call it from My world class?
My guess is that I can use some sort of callback, but I don't understand them!
/* Callback invoked when the surface dimensions change. */
public void setSurfaceSize(int width, int height) {
// synchronized to make sure these all change atomically
synchronized (mSurfaceHolder) {
mCanvasWidth = width;
mCanvasHeight = height;
world.getViewPort().updateViewPortSize(width,height);
}
}
Callback functions are pretty straightforward in Java. The way to do it is to simply define some interface A that has a single method m(), then add a collection of type A to your World class. Then, at some point in your World object you want to iterate over your A collection and call the method m() on each element. To add "callback functions" to your World, you then simply define some class that implements your interface A and put it in the collection of A objects in your World class. For example,
public interface CallbackFunction
{
public void execute(int a, int b);
}
public class World
{
List<CallbackFunction> callbackFunctions;
public void addCallback(CallbackFunction f)
{
callbackFunctions.add(f);
}
private void updateWorld()
{
// This loop could be anywhere in your World class
for(CallbackFunction f : callbackFunctions)
{
f.execute(<some int>, <some int>);
}
}
}
Then to add a function to your World:
world.addCallback(new CallbackFunction()
{
public void execute(int a, int b)
{
// Do some stuff
}
}
I leave the rest up to you, but this should give you a good idea of how callbacks are typically implemented in Java.
You don't need to store a general collection of callback functions either, you could have specific callback functions coupled with particular methods in your World class. For instance, your World class may have some method that sorts things by comparing two elements in a collection. To determine if one object should go before or after another, you could define a CallbackFunction interface that has a method that takes 2 things (like int's) and returns a value that indicates which thing should go first. For example,
public interface CallbackForSorting
{
public int compare(int a, int b);
}
public class World
{
List<Integer> thingsToSort;
public void sortThings(CallbackForSorter sorter)
{
int result = sorter.compare(thingsToSort.get(i), thingsToSort.get(i+1));
if(result == 0) // elements are equal
if(result == -1) // thingsToSort.get(i) is "less than" thingsToSort.get(i+1)
if(result == 1) // thingsToSort.get(i) is "greater than" thingsToSort.get(i+1)
}
}

Categories

Resources