Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dispatch user action to activities in backstack

Tags:

android

I'm developing social app. Let's assume I have a stack of activities A -> B -> C -> D. D is in foreground and user presses "like" button to something there (post, comment, user etc.) What is the best way to notify all other activities about this action in order to refresh their data? I see 3 options here:

  1. Use local database and some loaders to automatically refresh the data. However, it requires a lot of code if we have different data-models with shared data (for instance BasicUserInfo, UserInfo, DetailedUserInfo).
  2. Use EventBus with sticky events (producers for Otto). In this case I must notify ONLY backstack activities and ignore those that will be created. Also I have to manage events overriding.
  3. Use a simple observer pattern with WeakReferences to backstack activities. But then I have a problem with killed activities that are going to be re-instantiated.

Real example:

In Instagram: I open some specific user's profile (A), there I open some specific post (B), again profile (A) and so on A -> B -> A -> B -> A .... So it loads data from the web everytime. On the step "n+1" a new comment to the post appears. If I start going back through my backstack I will see that instagram has dispatched this "new" comment to all B activities without reloading any data from web. So I'm interesting how do they do it.

like image 692
user1049280 Avatar asked Oct 06 '15 08:10

user1049280


People also ask

What is task Backstack?

A task is a collection of activities that users interact with when trying to do something in your app. These activities are arranged in a stack—the back stack—in the order in which each activity is opened. For example, an email app might have one activity to show a list of new messages.

What code would you use to go back to a previous activity?

Android activities are stored in the activity stack. Going back to a previous activity could mean two things. You opened the new activity from another activity with startActivityForResult. In that case you can just call the finishActivity() function from your code and it'll take you back to the previous activity.


2 Answers

The main use case for a notification system (event, observer, BroadcastReceiver, ...) is when you want the recipient to act more or less immediately when something happens.

I think this is not the case here : the backstack activities don't need to act immediately as they are not visible. Besides they may even not exist anymore (killed / frozen). What they actually need is to get the latest data when they are back on the foreground (possibly after having been recreated).

Why not simply trigger the refresh in onStart() or onResume() (using a Loader or anything you already use) ?
If the 'liked' status needs to be persisted you could do it in D's onPause(). If not, the liked object could be stored in a global variable (which is actually what a sticky event is)

like image 119
bwt Avatar answered Oct 11 '22 13:10

bwt


You can use LocalBroadcastManager to notify your stacked activities that your Liked event has occured

Suppose in your Activity D:

private void liked() {
  Log.d("liked", "Broadcasting message");
  Intent intent = new Intent("like-event");
  // You can also include some extra data.
  intent.putExtra("message", "my like event occurs!");
  LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

Now it will notify all the activities who are registered with this broadcast reciever

for example in your Activity A,B,C :

@Override
public void onCreate(Bundle savedInstanceState) {

  ...

  // Register to receive messages.
  // We are registering an observer (mMessageReceiver) to receive Intents
  // with actions named "custom-event-name".
  LocalBroadcastManager.getInstance(this).registerReceiver(mLikeEventReceiver ,
      new IntentFilter("like-event"));
}

// Our handler for received Intents. This will be called whenever an Intent
// with an action named "like-event" is broadcasted.
private BroadcastReceiver mLikeEventReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    // Get extra data included in the Intent
    String message = intent.getStringExtra("message");
    Log.d("receiver", "Got message: " + message);
  }
};

@Override
protected void onDestroy() {
  // Unregister since the activity is about to be closed.
  LocalBroadcastManager.getInstance(this).unregisterReceiver(mLikeEventReceiver );
  super.onDestroy();
}

references : [http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html][1] [how to use LocalBroadcastManager? [https://androidcookbook.com/Recipe.seam?recipeId=4547][3]

  1. [1]: http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html

  2. [2]: how to use LocalBroadcastManager?

  3. [3]: https://androidcookbook.com/Recipe.seam?recipeId=4547

like image 39
Azfaar kabir Siddiqui Avatar answered Oct 11 '22 14:10

Azfaar kabir Siddiqui