Android handling runtime changes for multithreading

Example with server request

On configuration change, response is delivered to correct activity (or fragment):

Orientation change example

When user switched to other application, response will be cached, and when user returns back, delivered to correct activity (or fragment):

Application is not visible example

To implement this kind of logic, we just need to use publish-subscribe pattern (with Otto for example) and a little bit of magic:

Android attachable dialogfragment

Attaching dialog to view, or specific position


Call :
public class MainActivity extends Activity {
    private ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);
        imageView = (ImageView) findViewById(R.id.main_activity_image_view);
        findViewById(R.id.main_activity_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int[] loc = Utils.getCenterViewLocation(imageView, MainActivity.this);
                CustomDialog.attachTo(loc).show(getFragmentManager(), CustomDialog.class.getName());
            }
        });
    }
}

View location method :
public static int[] getCenterViewLocation(View view, Activity activity) {
    Rect windowRect = new Rect();
    activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(windowRect);
    int[] loc = new int[2];
    view.getLocationOnScreen(loc);
    loc[0] = loc[0] + view.getWidth() / 2;
    loc[1] = loc[1] + view.getHeight() / 2 - windowRect.top;
    return loc;
}

Android eventbus with local broadcast receivers

Simple bus with specified events

Usage example:
public class MainActivity extends Activity implements View.OnClickListener {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bus.register(receiver, Bus.Event.BUTTON_CLICKED, Bus.Event.THREAD_END);
        // or just Bus.register(receiver, Bus.Event.THREAD_END);
        ...
    }

    @Override
    public void onClick(View v) {
        Bus.post(Bus.Event.BUTTON_CLICKED);

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1337);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                Bus.post(Bus.Event.THREAD_END);
            }
        }).start();
    }

    public BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            switch (Bus.getEvent(intent)) {
                case BUTTON_CLICKED:
                    // do something on button click event

                    break;
                case THREAD_END:
                    // do something on thread end event

                    break;
            }
        }
    };

    @Override
    protected void onDestroy() {
        Bus.unregister(receiver);
        super.onDestroy();
    }
}