4

Java newbie here. I am using a third party library which gives me a function, say F(), the output of which dictates my logic. So I need the result of it to proceed further in my code.

The problem is F() does some I/O and so spawns off a thread to do the functionality. They gave me a few callbacks to implement which are called to return the status/values from the thread. This is fine except that the function F() returns immediately and the rest of my code keeps running. I don't want that as I have to allocate some objects based on the outcome of F() and so I really want to wait for F() to really finish.

This should be a problem people run into quite often. What is the correct way to deal with this? Is it a problem in my design or the third party library? Or did I not understand the library very well?

For the sake of completeness I am working on an android app and the library is the facebook sdk. The function is the single sign-on function authorize(). Though this is a generic enough problem that I thought is best addressed in the Java forum.

Thanks for any help. - P

garik
  • 5,669
  • 5
  • 30
  • 42
user220201
  • 4,514
  • 6
  • 49
  • 69

2 Answers2

5

I'm not familiar with the facebook SDK, but the normal mechanism to handle async operations like this is the Callable<> or Future<> interface: you'd create a service executor, pass in the Callable<> or Future<>, and then continue with your code.

An example can be found from the Future<> javadoc: http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html

Also see StackOverflow question/answer How to return object from Callable()

Community
  • 1
  • 1
Joseph Ottinger
  • 4,911
  • 1
  • 22
  • 23
4

Think about this:
The main thread of an android app is the thread that manages the UI, so if you want to wait until the method f() finishes, the screen will freeze. You probably will think that a good solution is to spawn a new thread and call the method f() inside it and use a callable or future to wait f(). Wrong. The code below the thread creation will execute so you will have the same problem.
Then how can you solve this? Simple. Redesign your application and use a listener, a.k.a. callback.

EDIT: A listener or callback is just a method (or methods) that a class A implement and passes this implementation to a class B to execute it. Class B doesn't know what he is executing, he just executes a method.

Example:

public class A{
    public A (){
        B b = new B (new B.Listener (){
            @Override
            void onResult (String result){
                //result is "Core dumped!"
            }
        });
        b.aMethod ();
    }
}

public class B{
    private final Listener listener;

    public static interface Listener{
        void onResult (String result);
    }

    public B (Listener listener){
        if (listener == null) throw new IllegalArgumentException ("The \"listener\" parameter cannot be null.");
        this.listener = listener;
    }

    public void aMethod (){
        //Do something interesant
        //...
        String error = "Core dumped!"

        //Call the listener
        listener.onResult (error);
    }
}

In your case you will have something similar to this:

public class YourClass{
    public void aMethod (){
        FaceBookClass fb = new FaceBookClass ();
        fb.setListenerToF (new FaceBookClass.FListener (){
            @Override
            void theCallback (Result aResult){
                //Do something with result
            }
        });
        fb.f ();

    }
}

public class FaceBookClass{
    public static interface FListener{
        void theCallback (Result aResult);
    }

    public void f (){
        ...
    }

    public void setListenerToF (FListener listener){
        ...
    }
}
Gabriel Llamas
  • 18,244
  • 26
  • 87
  • 112
  • Exactly my problem! You understood! The FB sdk provides a wait() method but that does not solve the problem if I call it in the main thread as it will just freeze the screen. What is this callback? I will have to check. Can you provide a link please? The problem is my view is being drawn based on the result of the login operation. – user220201 Apr 25 '11 at 14:59
  • Thanks for the answer. In this case what will the behavior of b.aMethod() be? Will it wait for the callback? Since aMethod() in essence is creating a thread and doing the interesting part in that thread. In my case specifically, the functin F() takes a DialogListener not the constructor. So I pass it in but F() returns immediately and after a point the callback gets called. But really want to wait for the callback to be called before proceeding with the rest of the logic. – user220201 Apr 25 '11 at 16:08
  • Ok. I have decided to just not base my logic on the outcome of the F(). I will have an intermediate state where I will show the user that he has logged in or not and make him click on something accordingly. – user220201 Apr 25 '11 at 17:52
  • b.aMethod() will execute your listener implementation (onResult(String) will be called) asynchronously, just when aMethod finishes. The method f() spawns a thread and when it finishes it will call your listener at any time. In other words, the code next to b.aMethod() or fb.f() will not wait the thread to finish but you have a component (listener) that is called when f() finishes and a result is passed to it. – Gabriel Llamas Apr 26 '11 at 07:33