3

I have a pojo method that generates a Bitmap. When done, I want to throw the Bitmap to a UI Activity. This is a sample, but here it is:

private void sendBitmap(Bitmap bitmap) {
    // TODO - I'm in the pojo where I want to send the bitmap
}

FYI: The UI Activity that I want to notify is outside of my project. I mean, my project is an SDK, such that another developer would be grabbing this information as soon as it becomes available.


I've been trying to figure this out but getting somewhat confused.

  1. Do I need a "callback" interface?
  2. Or a "listener" interface?
  3. Or both?

I have created a Callback Interface in my MyActivity. So far, so good. This is what it looks like so far:

import android.graphics.Bitmap;

public class MyActivity {

//  protected void whateverOtherMethods (Bundle savedInstanceState) 
//  {
//      .
//      .
//      .
//      .
//      .
//      .
//      
//  }

    /**
     * Callback interface used to supply a bitmap.
     */
    public interface MyCallback {
        public void onBitmapReady(Bitmap bitmap);
    }
}

The demo application's DoSomethingActivity can implement the Callback Interface that I have created. This is the implementation of the callback in the demo application's DoSomethingActivity:

private final MyCallback myCallback = new MyCallback() {

    @Override
    public void onBitmapReady(Bitmap bitmap) {
        // TODO - do something with the bitmap
    }
};

What is the step I'm missing to notify the callbacks? Maybe I almost have it, but I'm confused enough that I'm looking for a little help here.


UPDATE:

OK, I've added "implements" for my callback "BitmapCallback" interface into the pojo. Here it is:

public class ProcessImage implements BitmapCallback {

/**
 * pojo method to return bitmap
 */
private void sendBitmap() {
    this.onBitmapReady(bitmap);
}

@Override
public void onBitmapReady(Bitmap bitmap) {
    // we still need to send the bitmap to cusomer App.

}

I cannot move the callback definition from the SDK Activity, because I want the customer's application to implement the callback in their code to handle the bitmap when it is returned to the customer's application.

Here is the callback interface in my Activity:

public interface BitmapCallback {

    public void onBitmapReady(Bitmap processedBitmapy);
}

Here is the implementation in the customer's application:

private final BitmapCallback bitmapCallback = new BitmapCallback()  
{

    @Override
    public void onBitmapReady(Bitmap bitmap) {
        // TODO Auto-generated method stub          
    }
};

Call me dumb, but I'm having a hard time getting my head around this.

MikeOx
  • 167
  • 1
  • 1
  • 16
Patricia
  • 5,019
  • 14
  • 72
  • 152
  • what event are you looking at for callback? If its click event you should be looking at OnClickListener where you can call your custom listener. http://developer.android.com/reference/android/view/View.OnClickListener.html – Peshal Sep 23 '14 at 23:52
  • Why the down-votes? This is a callback based on some bitmap being changed. It has nothing to do with the UI. – Patricia Sep 24 '14 at 15:13

3 Answers3

7

You're almost there. You just need to tell your POJO about the callback instance. First, I would strongly recommend that you move the interface definition into the POJO (since conceptually it has to do more with that object than with your activity) or make the interface an independent type. The POJO should not know about types defined in the client class(es).

Then you have a choice:

  1. use a listener pattern: in your POJO add a field to store an instance of the callback (or something more complicated if you want to support calling back to multiple listeners) and a method for setting the listener. Call the method from your activity (or wherever is appropriate) when you create or are setting up the POJO.
  2. use a callback pattern: enhance the relevant API methods with a callback argument.

In either case, when the bitmap is ready you have the wiring to get the bitmap back to the activity.

EDIT

Here's an example of how this might be structured. You haven't provided any information about how you create your POJO or invoke the processing, so I invented something just as an example. It assumes that the processing is taking place in a separate thread, which will call back to the activity when done. You can modify this as needed. (In particular, this can be much simpler if the POJO is doing the work synchronously. Also, it would be better to use an AsyncTaskLoader rather than a plain vanilla thread so that it interacts properly with the Activity lifecycle.)

BitmapCallback.java

public interface BitmapCallback {
    public void onBitmapReady(Bitmap processedBitmap);
}

MyActivity.java

public class MyActivity extends Activity implements BitmapCallback {
    Handler mHandler; // initialize this in onCreate
    . . .

    public void onRequestImage() {
        ProcessImage processor = new ProcessImage();
        getImage(this /* , other actual args */);
    }

    @Override
    public void onBitmapReady(final Bitmap processedBitmap) {
        // since this may be called from a non-UI thread, we can't update
        // the UI directly.
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                // handle the bitmap (update the UI, etc.)
            }
        });
    }
}

ProcessImage.java

public class ProcessImage {
    public void getAnImage(final BitmapCallback callback /* , other formal args */) {
        new Thread() {
            @Override
            public void run() {
                Bitmap bitmap;
                . . . // do the work
                // then deliver the results
                callback.onBitmapReady(bitmap);
            }
        }.start();
    }
}
Muhammad Usman Bashir
  • 1,441
  • 2
  • 14
  • 43
Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • First, I want to thank you for the information you have provided. I'm still struggling with this. Please see my **UPDATE** added to the end of the question, above. – Patricia Sep 24 '14 at 16:08
  • @Lucy - You have the logic backwards. It is the activity, not the pojo, that should implement the callback functionality. The _definition_ of that functionality should not be tied to the definition of the activity; otherwise the pojo will have a dependency on the activity, which is undesirable. I've added a concrete example that shows what I mean. – Ted Hopp Sep 24 '14 at 17:52
1

Create an instance of your listener in your pojo class

MyCallback callback;

and set onBitmapReady inside sendBitmap method to notify activity

private void sendBitmap(Bitmap bitmap) {
    // TODO - I'm in the pojo where I want to send the bitmap
    callback.onBitmapReady();
}
Fatih Santalu
  • 4,641
  • 2
  • 17
  • 34
  • It's not that easy. The instance is null and you can't instantiate an interface. When I finally get this, I'll feel even dumber than I feel right now. Thanks for your help. – Patricia Sep 24 '14 at 16:10
0

It turned out that in order to make a callback work from inside an intent I needed to make the callback Serializable. After trying that and continuing to get an error reflecting that somehow the Activity was trying to serialize itself, which was causing the application to crash.

So I went back to the all wise one, Ted Hopp. Per Ted's advice, I ended up using Broadcasting. See the thread here: how to use LocalBroadcastManager?

Great advice, Ted, this solved my problem.

Lesson learned: If you are trying to use a callback from an SDK back to an "external" application and have problems, try looking at Broadcasting instead.

Community
  • 1
  • 1
Patricia
  • 5,019
  • 14
  • 72
  • 152