Passing "this" from Java Interface to another Class - java

Giving the following class of my android Project :
Preview extends SurfaceView implements SurfaceHolder.Callback
and
A extends Doc
I don't really know how to ask and I know that this is not really good but I want that from Preview, I call an abstract method of Doc. In this Doc's method, I have to call a method of the previous Object of Preview.
This is an example :
From Preview.java :
Doc _doc = new A();
private void myMethod() {
this._doc.process(this)
}
From A.java :
#Override
public void process(Preview p) {
p.processA();
}
The problem is that I got an error :
The method process(Preview) in the type Doc is not applicable for the arguments (new Camera.PreviewCallback(){})
However, I can't change this judging by the fact that I want to call the method from Preview. I tried many thing such as cast etc. None of them works.
Thanks for your help !
PS : I am on Eclipse under Windows.

Assuming you are calling A.process(this) from an anonymous inner class (of type Camera.PreviewCallback I presume, hence the error message), you have to write A.process(Preview.this), since a standalone this refers to the inner class and not to the Preview instance.

The method process(Preview) in the type Doc is not applicable for the arguments (new Camera.PreviewCallback(){})
It simply means you are passing the object of Camera.PreviewCallback but in your method public void process(Preview p) You want an object of Preview.
If you have written this code in side an anonymous class, then this won't point to the Preview class. It will point to the object of inner anonymous class.
Thus you need to write A.process(Preview.this)

Related

Is there a way to delegate the implementation of an interface to a different class?

I've been working on Xamarin for the past couple of years along with Android studio and I decided to create an application for a friend (full source code here https://github.com/nekrull/waiter don't be too harsh please :) )
The idea is that there is a base activity which exchanges fragments when a new screen should appear.
Fragments have everything that has to do with user interaction and the activity they are attached to handles the business logic.
To do this I have a base class CoreActivity/DataActivity which has some methods most Fragments use (like blocking the back button) and some helper methods (like calling a method on an attached fragment of a specific class) , a CoreInteraction that responds to this activity and
CoreFragment/AttachedFragment which is used as the base of all view fragments
so for example the view fragment would look like this:
public class GroupsFragment extends AttachedFragment<GroupsFragment.GroupsInteraction> {
//this is what we expect to be able to call in the parent
public interface GroupsInteraction extends CoreInteraction {
Group get_shown_group();
void new_group();
void select_parent();
}
}
which is basically a fragment that expects its attached activity to be able to respond to the interaction methods.
the activity fragment would look like this:
public class MainActivity extends DataActivity<MainData> implements
GroupsFragment.GroupsInteraction, (other interactions here) {
}
The problem is that since the application I'm working on has only one Activity with many small screens, the code inside the base activity will get big, that does not cause a problem with the application or compiling or anything else. But it makes it really hard to find what I'm looking for easily.
What I used to do in Xamarin is something like this:
public partial class MainActivity : DataActivity<MainData> {
}
for the initialization activity and then each interaction would get its own file like this:
public partial class MainActivity : GroupsInteraction {
}
It had the same effect (since the class is compiled as a single class) but the code would be tidy and easy to read.
Obviously there are no partial classes in Java, but is there a way to delegate the implementation of an interface to another class?
Something along the lines of saying "when you're invoking a method from interface a, invoke it from that class" without actually writing stuff like :
public Group get_shown_group() {
return new GroupHandler(this).get_shown_group();
}
public void new_group() {
new GroupHandler(this).new_group();
}
public void select_parent() {
new GroupHandler(this).select_parent();
}
Thanks in advance for any help you can provide
Something along the lines of saying "when you're invoking a method from interface a, invoke it from that class"
Taking you literally what you describe is plain delegation, a class does not implement some or any functionality itself, instead it wraps a class implementing the desired functionality, calling the methods of said wrapped class. You could even switch implementation at runtime, just changing the wrapped class as you go (assuming the classes share a common interface, of course). Of course that does not "spare" you from writing the delegations yourself.
class Wrapper implements GroupsInteraction {
private final GroupInteraction gi;
public Wrapper(GroupsInteraction gi) {
this.gi = gi;
}
Group get_shown_group() {
return this.gi.get_shown_group();
}
// ... other interface impls
}
Additionally, you should keep the GroupHandler as a member instead of creating a new Object each time, so
public Group get_shown_group() {
return new GroupHandler(this).get_shown_group();
}
becomes
public Group get_shown_group() {
return this.groupHandler.get_shown_group();
}
You can try Delegation Pattern
BaseActivity {
MyDelegateClass delegate;
void example() {
delegate.example();
}
}
P.S. both activity and delegate implements same interface
Details here

Extending StackView or AdapterViewAnimator seems impossible

I am attempting to make a custom implementation of Android's StackView by extending AdapterViewAnimator myself. There are several methods contained in AdapterViewAnimator which would prove useful to my subclass, and so I put my subclass in the same package android.widget hoping to gain access to them since they are package-level methods:
void configureViewAnimator(int numVisibleViews, int activeOffset) {
if (activeOffset > numVisibleViews - 1) {
// Throw an exception here.
}
mMaxNumActiveViews = numVisibleViews;
mActiveOffset = activeOffset;
mPreviousViews.clear();
mViewsMap.clear();
removeAllViewsInLayout();
mCurrentWindowStart = 0;
mCurrentWindowEnd = -1;
}
Note that this method is a package level method, which is why my subclass needs to be in android.widget as well. Even so, the compiler (Java 7) tells me that the method does not exist, and so I cannot call the method on my superclass in my class:
package android.widget;
public class Foo extends AdapterViewAnimator {
public void init(){
super.configureViewAnimator(3,1); // Method does not exist.
}
}
Am I missing something here? Why can't my subclass call the superclass package-level method?
You can refer to https://groups.google.com/forum/#!msg/android-developers/poC2Xyh-G4w/zKLBPNTryYMJ
"Android.jar now contains only the public APIs. If you compile against this jar, you are guaranteed your app will run against future versions of Android. As part of the process that removes private APIs from android.jar, the code is stubbed out, because it's never executed so there's no reason to make the SDK much bigger because of it."
This explain why the method configureViewAnimator is not found as you are compiling against the android.jar, which include only public API(configureViewAnimator is a package private method)

Getting the actual class used for a MethodInvocation rather than the declaring class

I'm digging through a web application in an effort to fix some problems. The application uses Tomcat, Jersey and Guice. One of the issues is occurring in a MethodInterceptor used for authorization purposes. Here's the method, trimmed to the relevant part:
public Object invoke(MethodInvocation invoc) throws Throwable {
// ...
//Check that the annotation actually exists
if(! invoc.getMethod().getDeclaringClass().isAnnotationPresent(Tool.class))
{
throw new BaseException("...");
}
// ...
}
Now the problem is that some of the "web-facing" methods are inherited from a parent class without being overridden in the child. If I understand getDeclaringClass() correctly, it will return the parent class in this case, but what we really want here is the child class. Some testing seems to confirm this--if I override the method in the child class everything is fine, but if I don't put in the override the exception is thrown.
So, given a MethodInvocation object, is there a way to trace it back to the "actual" class instantiated, rather than the class where the method was declared? Or is some other approach necessary? Worst-case, I could just annotate each method as necessary rather than annotating the class.
Sorry if this is a long-winded question for an easy answer - my Java is pretty rusty.
Simple enough, needed to use getThis().getClass() on the MethodInvocation instead of getMethod().getDeclaringClass():
if(! invoc.getThis().getClass().isAnnotationPresent(Tool.class))
{
throw new BaseException("...");
}
Although in my case, Guice complicated things a bit by putting in an auto-generated child class (e.g., a class name ending in "$$EnhancerByGuice..." That was fixed by moving one up the tree with getSuperclass():
if(! invoc.getThis().getClass().getSuperclass().isAnnotationPresent(Tool.class))
{
throw new BaseException("...");
}
It looks like that the answer is No. I created simple test to check it:
class Run implements Runnable {
#Override
public void run() {
}
}
class Run2 extends Run{}
Method method = Run2.class.getMethods()[0];
System.out.println(method);
As we can see in debug window method doesn't have any information of class Run2:
I guess it would be better to stick on actual methods with its annotations rather then on actual class instances where these methods get invoked.

Can I instantiate my Activity…and should I?

NEWBIE ALERT!
Here's the situation. I've got an Android ListActivity class (AppWindow) that contains all the methods that create and update the UI for my application. It includes a method (refreshWindow) that calls setListAdapter, and therefore must be non-static. So far, I've been using a separate class (FileHandler) to perform manipulations on files that are referenced by the AppWindow class. I've reached a point where I want to call the refreshWindow method when a certain file manipulation has been performed. However, since the refreshWindow method is non-static, it seems that I would need to instantiate AppWindow and call the method through that instance. However, I'm not sure how to do this or if it's even a good idea. Perhaps I just need to move all of the FileHandler logic into AppWindow, although I'd prefer to keep them separate.
Here's a description of the situation in code form:
AppWindow.java
...
public class AppWindow extends ListActivity {
...
void refreshWindow() {
...
setListAdapter(new ListAdapter());
...
}
...
}
FileHandler.java
...
class FileHandler extends Activity {
...
static void doStuffToFiles() {
...
AppWindow appWindow = new AppWindow();
appWindow.refreshWindow();
...
}
...
}
Should I be doing this? If so, how do I properly instantiate AppWindow?
Create a static member variable; say act; in FileHandler
On creation of ListActivity set the variable act using 'this' variable of activity
Now you can access activity instance from FileHandler.
Update the UI must be in the UI thread. You can use handler to handle the message. The handler's constructor can contain the activity, so you can use it.

Help passing a complex object via a JSNI call to get around static scope

So I've got a GWT app and I'm trying to invoke a function to change the app's view from an outside button. Normally this is called with as "this.internalFunction('string')". The problem is that JSNI works via static methods and so the object in question is lost. The solution: pass the app's object itself to the JSNI call and invoke that object's function calls from there! The problem to the solution: this doesn't work. :(
Class looks something like this:
package blah.package;
public class Foo implements A, B {
public native void initChangeFunc() /*-{
$wnd.jsChangeView = $entry(this.#blah.package.Foo::doSomething
(Lblah.package.Foo;)(this));
//Pass this to the function call to do calls on app object
}-*/;
public void doSomething(Foo obj) {
//Change view here.
obj.internalFunction("parameter");
};
public void internalFunction(String param) {
//Do stuff with param.
}
}
On module load, call initChangeFunc() and access jsChangeView() on the page itself.
Compile errors suggest that the compiler can't find blah.package.Foo, and that's because my parameter type signature (the Lblah.package.Foo part) is wrong.
[ERROR] Line 64: Expected a valid parameter type signature in JSNI method reference
First thing's first, try not to break the line calling Foo::doSomething, and check to see if it helps.

Categories