After a whole night spent in test (without any luck) I need some support with my interface.
I'm working directly on the Android frameworks and I created a class that works as a Binder with a WeakHashMap to control the callbacks.
Here is the code:
MyCallback:
public interface MyCallback {
public void fire();
}
MyBinder:
public static WeakHashMap<String, MyCallback> mCallbacks =
new WeakHashMap<String, MyCallback>();
public static void setup(MyCallback callback) {
if(mCallbacks.get(callback.getClass().getName()) == null) {
mCallbacks.put(callback.getClass().getName(), callback);
}
}
public static void letsgo() {
Log.d("size", " " + mCallbacks.size()); // IMPORTANT
for (MyCallback cb : mCallbacks.values()) {
cb.fire();
}
}
These 2 classes are written into frameworks so I created 2 test applications with a simple class that implements my interface:
public class FirstApp implements MyCallback {
public FirstApp() {
MyBinder.setup(this);
}
#Override
public void fire() {
Log.d("app1", "fired");
}
}
public class SecondApp implements MyCallback {
public SecondApp() {
MyBinder.setup(this);
}
#Override
public void fire() {
Log.d("app2", "fired");
}
}
Ok at this point I made another class (all these 3 classes, so the 2 that implements the interface and the following one are written into different packages)
In this third class i just call: MyBinder.letsgo();
The issue I'm facing, and that I'm trying to solve since... 8/9 hours is that: If i run letsgo() on the third pack the logs shown 0 for the callbacks WeakHashMap size. if i run letsgo() on the second package it works but it only fires the callback in the same package. the same if i run it on the first package.
I tried also with HashMap instead of WeakHashMap since i red that objects must be referenced but without any luck. I wonder if someone can help me and let me go sleep :D Thanks!
Related
I have a java object that gets a listener object as a parameter. This listener should implement a certain java abstract class.
I'm trying to prevent writing this in java, because I use an SDK that comes in a jar file, and to call a jar file from a java file, I'll need to create one jar file that includes them both (see Unity3D with multiple jars (android jar + pure java lib))
This answer explains my error but doesn't give a solution.
AndroidJavaProxy is not an interface
I'll try to be more detailed:
I've got the Listener class (which is inside the jar file):
public abstract class AttachCallback {
public AttachCallback();
public void onAttached(Sdk sdk);
}
My c# code is currently (and doesn't work):
public class AttachCallback : AndroidJavaProxy
{
public AttachCallback() : base("com.example.AttachCallback")
{
}
public void onAttached(AndroidJavaObject sdk)
{
Debug.Log("-----Attached------");
}
}
Currently, I get java.lang.IllegalArgumentException: com.example.AttachCallback is not an interface
So, is there a way to do this?
Thanks in advance,
Chaim
First: read this article. Android Java Proxy can implement only interfaces. So you should create interface in java. Something like:
public interface IAttachable
{
public void onAttached(Sdk sdk);
}
In your AttachCallback class you add this interface like:
public abstract class AttachCallback implements IAttachable {
public IAttachable unityCallback;
public void onAttached(String sdk)
{
unityCallback.onAttached(sdk);
}
}
Then in your unity class, create JavaProxy
public class AttachCallback : AndroidJavaProxy
{
public AttachCallback() : base("com.example.IAttachable")
{
}
public void onAttached(AndroidJavaObject sdk)
{
Debug.Log("-----Attached------");
}
}
For attaching your Unity Proxy you should pass your AttachCallback to java, something like:
public void AddAttachToJava()
{
AttachCallback callback = new AttachCallback();
//Passing to activity, but you can do whatever you want
using (AndroidJavaClass javaClass = new AndroidJavaClass("your activity class name"))
{
using (AndroidJavaObject activity = javaClass.GetStatic<AndroidJavaObject>("mContext"))
{
activity.Call("attachUnityCallback", callback);
}
}
}
Your java method in activity should look like this:
public void attachUnityCallback(IAttachable attachable)
{
// if AttachCallback is created
attachCallback.unityCallback = attachable;
attachCallback.onAttached(sdk);
}
I am trying to write a function that gets a list of games and use a callback to load the results. This is what i have right now:
public void getAllGames(OrderedRealmCollectionChangeListener<RealmResults<Game>> callback) {
realm.where(Game.class).findAllSortedAsync("startTime").addChangeListener(callback);
}
I want to make decouple Realm(OrderedRealmCollectionChangeListener and RealmResults) from this function, but I don't know how. I tried creating a listener that extends the OrderedRealmCollectionChangeListener but I am still stuck with the RealmResults, and when I try to extend that it said BaseRealm is private so it is impossible for me to create a constructor for that. How can I make it look like this:
public void getAllGames(SomeListener<SomeList<Game>> callback) {
realm.where(Game.class).findAllSortedAsync("startTime").addChangeListener(callback);
}
Derp, all I should have done is write the callback behaviour inside the getAllGames function:
public void getAllGames(SomeListener<List<Game>> callback) {
realm.where(Game.class).findAllSortedAsync("startTime").addChangeListener(new OrderedRealmCollectionChangeListener<RealmResults<Game>>() {
#Override
public void onChange(RealmResults<Game> collection, OrderedCollectionChangeSet changeSet) {
callback.callback(collection);
}
});
}
I have a PicoContainer which caches all components. Since it caches all components, I expect it to call start, stop and dispose at the appropriate points in the container lifecycle.
However, I'm finding that if I construct a component using a FactoryInjector, these methods don't get called at all, despite that component also being cached.
Take the following example:
import java.lang.reflect.Type;
import org.picocontainer.Characteristics;
import org.picocontainer.DefaultPicoContainer;
import org.picocontainer.Disposable;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.PicoContainer;
import org.picocontainer.Startable;
import org.picocontainer.injectors.FactoryInjector;
public class PicoContainerFactoryTest {
public static void main(String[] args) {
MutablePicoContainer container =
new DefaultPicoContainer().as(Characteristics.CACHE);
try {
System.out.println("Adding components...");
container.addComponent(InstanceService.class,
new InstanceServiceImpl());
container.addComponent(ConstructedService.class,
ConstructedServiceImpl.class);
container.addAdapter(
new FactoryConstructedServiceAdapter());
System.out.println("Starting...");
container.start();
// Even this doesn't trigger it. :(
//container.getComponent(FactoryConstructedService.class);
System.out.println("Stopping...");
container.stop();
}
finally
{
System.out.println("Disposing...");
container.dispose();
}
}
public interface InstanceService
extends Startable, Disposable {}
public interface ConstructedService
extends Startable, Disposable {}
public interface FactoryConstructedService
extends Startable, Disposable {}
private static class InstanceServiceImpl extends Impl
implements InstanceService {
public InstanceServiceImpl() {
super("InstanceServiceImpl");
}
}
public static class ConstructedServiceImpl extends Impl
implements ConstructedService {
public ConstructedServiceImpl() {
super("ConstructedServiceImpl");
}
}
private static class FactoryConstructedServiceAdapter
extends FactoryInjector<FactoryConstructedService> {
public FactoryConstructedServiceAdapter() {
super(FactoryConstructedService.class);
}
#Override
public FactoryConstructedService getComponentInstance(
PicoContainer picoContainer, Type type) {
return new FactoryConstructedServiceImpl();
}
private static class FactoryConstructedServiceImpl extends Impl
implements FactoryConstructedService {
public FactoryConstructedServiceImpl() {
super("FactoryConstructedServiceImpl");
}
}
}
public static class Impl implements Startable, Disposable {
private final String name;
public Impl(String name) {
this.name = name;
System.out.println(" " + name + "#<init>");
}
#Override
public void start() {
System.out.println(" " + name + "#start");
}
#Override
public void stop() {
System.out.println(" " + name + "#stop");
}
#Override
public void dispose() {
System.out.println(" " + name + "#dispose");
}
}
}
The output of running this is as follows:
Adding components...
InstanceServiceImpl#<init>
Starting...
ConstructedServiceImpl#<init>
InstanceServiceImpl#start
ConstructedServiceImpl#start
Stopping...
ConstructedServiceImpl#stop
InstanceServiceImpl#stop
Disposing...
ConstructedServiceImpl#dispose
InstanceServiceImpl#dispose
So on start(), the component I created and injected as an instance is started. The component I injected via constructor injection gets constructed and then started. But nothing is seen from the component I injected via the factory.
As far as the documentation goes, the Javadoc for FactoryInjector shows #start, #stop and #dispose methods, which appear to be intended for the factory itself to do its own lifecycle stuff, not for the components the factory spins out.
A quick look at the source shows that the adapter implementing ComponentLifecycle will have its methods called, but it isn't immediately clear how to hook it in. If I look at the other implementing classes, practically everything seems to delegate to something else, making it difficult to figure out what is really happening.
What is the proper way to do this? Is there even a proper way to do this?
FactoryConstructedServiceAdapter should implement LifecycleStrategy
and have
#Override
public boolean hasLifecycle(Class<?> type) {
return true;
}
Basically, that's all, factory will be included in the standard lifecycle and can manage the components AND the actual instantiation for FactoryConstructedServiceImpl will be called (if you don't need lifecycle on a component provided by your factory and just wonder why it's not instantiated, keep in mind that factories are lazy and you don't see "FactoryConstructedServiceImpl#init" in log until you actually wire or request the component).
Take InstanceAdapter if you need a big example.
I have a simple application and want to make it testable. I m new in this area.
Here is a simple Presenter, taking in mind this code ,could you advice or give me some example how to test it.
public class SomePresenter extends Presenter<MainPanelPresenter.Display>
{
public interface Display extends WidgetDisplay
{
HasClickHandlers getAddButton();
HasClickHandlers getDeleteButton();
void setData(ArrayList<Person> data);
ArrayList<String> getSelectedRows();
Widget asWidget();
}
private final DispatchAsync dispatcher;
public static final Place PLACE = new Place("main");
#Inject
public SomePresenter(DispatchAsync dispatcher, EventBus eventBus, Display display)
{
super(display, eventBus);
this.dispatcher = dispatcher;
bind();
}
protected void onBind()
{
display.getAddButton().addClickHandler(new ClickHandler()
{
public void onClick(ClickEvent event)
{
eventBus.fireEvent(new AddButtonEvent());
}
});
display.getDeleteButton().addClickHandler(new ClickHandler()
{
public void onClick(ClickEvent event)
{
ArrayList<String> list = display.getSelectedRows();
deletePerson(list);
}
});
}
....
private void loadDbData()
{
..........
}
private void deletePerson(ArrayList<String> ids)
{
..........
}
}
Edit:
What does the Presenter is, load initial data from db, have 2 buttons add and delete.
When add is press then a new form is load and user is able to input data and save to the db,
delete button just delete person from db.
Thanks
The general idea of unit testing such a class would be, like for any other class :
create Mock version of the dependencies (Display, EventBus, etc...)
set expectations on what the depdencies should do when the Presenter works
exercice the Presenter and check the expectations
However there are a couple of issues with your version of the Presenter :
The loadDbData() method is not showed, but I assumed it means the Presenter also has access to some other component that does the fetching. Can this component be abtracted in a dependency, and mocked liked the rest ?
Then there is the testing of bind(). The only responsibility of your Presenter in this method is to set up callbacks on some buttons provided by the Display. What you want to test is both :
That the callbacks are set
That the set callbacks do the expected things
A few ideas to help with the later :
You can reduce the coupling between Presenter and Button. If possible, change the Display interface from :
Button getAddButton();
to
addAddButtonClickedHandler(ClickHandler);
This means your Presenter does not have to use a Display object that returns actual BUtton
You can reduce the callbacks content to calling a single method, that you can then test in isolation
protected void bind() {
display.addAddButtonClickHandler(new ClickHandler() {
public void onClick(ClickEvent) {
fireAdded();
}
});
}
// The fireAdded function can be tested independenty of the Display, potentially with
// a mock EventBus
protected void fireAdded() {
event.fireEvent(....)
}
If you really want to check that the callbacks are properly set, than you can use a 'Dummy' implementation of the Display class, that provides you a list of all the callbacks, and let you call them
private class DummyDisplay implements Display {
private List<ClickHandler> addButtonClickHandlers;
public void addAddButtonClickHandler(ClickHandler handler) {
addButtonClickHandlers.add(handler);
}
public void fireAddButtonClick() {
for (ClickHandler h in addButtonClickHandlers) {
h.onClick(new ClickEvent());
}
}
// ....
}
Then your test would :
create a presenter with such a dummy display
use bind to set the callbacks
use display.fireAddButtonClick() to simulate a user clicking
check that has the result of the click, the effects of fireAdded are seen
This type of class (that mostly glue other classes together) can tend to be hard to test ; at some point, it the other classes are thoroughly tested it can become slightly counter productive to concentrate on the gluers, rather than the glued.
Hoping this helps.
Very typically I have a situation where a given object will need to have many listeners. For instance, I might have
class Elephant {
public void addListener( ElephantListener listener ) { ... }
}
but I'll have many such situations. That is, I'll also have a Tiger object that'll have TigerListeners. Now, TigerListeners and ElephantListeners are quite different:
interface TigerListener {
void listenForGrowl( Growl qrowl );
void listenForMeow( Meow meow );
}
while
interface ElephantListener {
void listenForStomp( String location, double intensity );
}
I find that I always have to keep re-implementing the broadcasting mechanism in each animal class, and the implementation is always the same. Is there a preferred pattern?
Instead of each Listener having specific methods for every event type you can send it, change the interface to accept a generic Event class. You can then subclass Event to specific subtypes if you need, or have it contain state such as double intensity.
TigerListener and ElephentListener then become
interface TigerListener {
void listen(Event event);
}
In fact, you can then further refactor this interface into a plain Listener:
interface Listener {
void listen(Event event);
}
Your Listener implementations can then contain the logic that they need for the specific events they care about
class TigerListener implements Listener {
#Overrides
void listen(Event event) {
if (event instanceof GrowlEvent) {
//handle growl...
}
else if (event instance of MeowEvent) {
//handle meow
}
//we don't care about any other types of Events
}
}
class ElephentListener {
#Overrides
void listen(Event event) {
if (event instanceof StompEvent) {
StompEvent stomp = (StompEvent) event;
if ("north".equals(stomp.getLocation()) && stomp.getDistance() > 10) {
...
}
}
}
}
The key relationship between the subscriber and the publisher is that the publisher can send events to the subscribers, it isn't necessarily that it can send it certain types of events - this type of refactoring pushes that logic from the interface down into the specific implementations.
This is a more general answer for people who come here just wanting to make a listener. I am summarizing Creating Custom Listeners from CodePath. Read that article if you need more explanation.
Here are the steps.
1. Define an Interface
This is in the child class that needs to communicate with some unknown parent.
public class MyClass {
// interface
public interface MyClassListener {
// add whatever methods you need here
public void onSomeEvent(String title);
}
}
2. Create a Listener Setter
Add a private listener member variable and a public setter method to the child class.
public class MyClass {
// add a private listener variable
private MyClassListener mListener = null;
// provide a way for another class to set the listener
public void setMyClassListener(MyClassListener listener) {
this.mListener = listener;
}
// interface from Step 1
public interface MyClassListener {
public void onSomeEvent(String title);
}
}
3. Trigger Listener Events
The child object can now call methods on the listener interface. Be sure to check for null because there might not be anyone listening. (That is, the parent class might not have called the setter method for our listener.)
public class MyClass {
public void someMethod() {
// ...
// use the listener in your code to fire some event
if (mListener != null)
mListener.onSomeEvent("hello");
}
// items from Steps 1 and 2
private MyClassListener mListener = null;
public void setMyClassListener(MyClassListener listener) {
this.mListener = listener;
}
public interface MyClassListener {
public void onSomeEvent(String myString);
}
}
4. Implement the Listener Callbacks in the Parent
The parent can now use the listener that we set up in the child class.
Example 1
public class MyParentClass {
private void someMethod() {
MyClass object = new MyClass();
object.setMyClassListener(new MyClass.MyClassListener() {
#Override
public void onSomeEvent(String myString) {
// handle event
}
});
}
}
Example 2
public class MyParentClass implements MyClass.MyClassListener {
public MyParentClass() {
MyClass object = new MyClass();
object.setMyClassListener(this);
}
#Override
public void onSomeEvent(String myString) {
// handle event
}
}
I think you're doing it correct, since your interfaces have semantic value and express what they are listening to (e.g. growls and meows instead of stomps). With a generic approach, you may be able to reuse the broadcasting code, but you may lose the readability.
For example, there is the java.beans.PropertyChangeSupport which is a utility for implementing Oberservers listening for value changes. It does the broadcasting, but you still need to implement the method in your domain class and delegate to the PropertyChangeSupport object. The callback methods are meaningless by themselves, and the events broadcasted are String-based:
public interface PropertyChangeListener extends java.util.EventListener {
void propertyChange(PropertyChangeEvent evt);
}
Another one is java.util.Observable which provides the broadcasting mechanism, but it's also not the best thing imho.
I like ElephantListener.onStomp()
A different options is the Whiteboard Pattern. This disconnects the publisher and subscriber from each other, and neither will contain any broadcasting code. They both simply use a messaging mechanism for pub/sub and neither has any direct connection to the other.
This is a common model for messaging in an OSGi platform.
I created a Signals library just for this purpose. To remove the boiler code involved in "re-implementing the broadcasting mechanism."
A Signal is an object created automatically from an interface. It has methods for adding listeners and dispatching/broadcasting events.
It looks like this:
interface Chat{
void onNewMessage(String s);
}
class Foo{
Signal<Chat> chatSignal = Signals.signal(Chat.class);
void bar(){
chatSignal.addListener( s-> Log.d("chat", s) ); // logs all the messaged to Logcat
}
}
class Foo2{
Signal<Chat> chatSignal = Signals.signal(Chat.class);
void bar2(){
chatSignal.dispatcher.onNewMessage("Hello from Foo2"); // dispatches "Hello from Foo2" message to all the listeners
}
}
In this example, Foo2 is the broadcaster of new messages over the Chat interface. Foo then listen to those and log it to logcat.
Note that there are no limitations on what interfaces you can use
You also have some sugar API for registering for only the first broadcast and unregistering from all the signals at once(Via the SignalsHelper)
Try the java kiss library and you will get this done faster and more correctly.
import static kiss.API.*;
class Elephant {
void onReceiveStomp(Stomp stomp) { ... }
}
class Tiger {
void onReceiveMeow(Meow meow) { ... }
void onReceiveGrowl(Growl growl) { ... }
}
class TigerMeowGenerator extends Generator<Meow> {
// to add listeners, you get:
// addListener(Object tiger); // anything with onReceiveMeow(Meow m);
// addListener(meow->actions()); // any lambda
// to send meow's to all listeners, use
// send(meow)
}
The generator is thread-safe and efficient (writing correct generators is the hardest part). It is an implementation of the ideas in
Java Dev. Journal - Skilled Listening in Java (local copy)