1

I have an Android app that contains a users list with an Avatar for each user. The avatar image file is stored as a local .png file in the apps cache folder. From time to time, another service updates the avatar png files with more current ones (but in no regular order), and I would like to have my list of avatar ImageView update with the new .png files as they are saved to disk.

I have tried subclassing ImageView and adding a FileObserver property to it, however, this isn't seeming to be the most effective.

Does anyone have any recommendations on how to "live" bind a .png to an ImageView so that it will updates if/when the image file on disk changes?

I'm not sure if I should be looking into DataBinding or not because this seems overkill to me.

Brett
  • 11,637
  • 34
  • 127
  • 213
  • 1
    Does the service belong to you? In that case, the service could send a broadcast message after saving the file and notify the activity/fragment of the change, and refresh the ImageView. – Logain May 12 '17 at 03:57

1 Answers1

0

You can register BroadcastReceiver at activity and receive notifications from your service.

Firstly, you need to create an implementation of BroadcastReceiver like this:

public class YourBroadcastReceiver extends BroadcastReceiver {
    /**
     * Listener interface for received broadcast messages.
     */
    public interface YourBroadcastListener {
        void receivedBroadcast();
    }

    /**
     * The Intent action that this Receiver should filter for.
     */
    public static final String ACTION = "com.your.package.IMAGES_UPDATED";

    private final YourBroadcastListener mListener;

    public YourBroadcastReceiver(YourBroadcastListener listener) {
        mListener = listener;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        if (mListener != null)
            mListener.receivedBroadcast();
    }
}

Next, you need to register YourBroadcastReceiver in your activity:

public class MainActivity extends Activity implements YourBroadcastListener {

    private YourBroadcastReceiver mReceiver;

    @Override
    protected void onResume() {
        super.onResume();

        if(mReceiver == null){
            mReceiver = new YourBroadcastReceiver(this);
            registerReceiver(mReceiver, new IntentFilter(YourBroadcastReceiver.ACTION));
        }
    }


    @Override
    protected void onPause() {
        super.onPause();

        if(mReceiver != null){
            unregisterReceiver(mReceiver);
            mReceiver = null;
        }
    }

    @Override
    public void receivedBroadcast() {
        // Received a broadcast notification that the images has changed - reload it
    }
}

And the last, your service need to send brodcast notifications to your activity:

Intent i = new Intent("com.your.package.IMAGES_UPDATED");
sendBroadcast(i);

Take a note: your action string need to be unique to avoid collisions with another applications.

Sergei Bubenshchikov
  • 5,275
  • 3
  • 33
  • 60
  • I would go a bit further and recommend you to use LocalBroadcastManager if your image updater service is hosted in the same app and process. It's much more lightweight (no serialization and cross-process routing overhead) and safer (no action collisions). Also, you can put the receiver directly in a custom ImageView. – BladeCoder May 12 '17 at 11:46