Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

startActivityForResult not working properly with launchMode singleInstance

I'd like Activities on my application's Activity stack to only have one instance. I have several screens which are ListActivities and I'd like to not go through the pain and suffering of updating the lists in a previous instance of the ListActivity when another instance of that ListActivity is changed (added to, edited, removed from, etc) (or is there an easy way to do this?).

Note: I've read that singleTop will accomplish this (though it destroys the Activity if you hit the back button), but it does not work. I have a menu and if I go to my Inbox screen, then I go to my QuickList screen, and then I go to my Inbox screen again, it creates a new Inbox Activity.

Right now, on my ListActivities, I have launchMode set to singleInstance. The problem is: If I launch another Activity using startActivityForResult, the onActivityResult handler fires right away (before the new Activity is created). When I perform the necessary action on the next screen to return the result, the onActivityResult handler does not fire.

What is going on?

Here is how I fire the new Activity:

Intent intentLaunchQuickList = new Intent(ActivityMyList.this, ActivityQuickList.class);
startActivityForResult(intentLaunchQuickList, REQUEST_QUICKLIST);

Here is how I return the result:

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);
    QuickListItem qlItem = m_Adapter.getItem(position);
    if (qlItem != null && qlItem.getQLId() != -1) {
        Intent data = new Intent();
        data.putExtra("ql_id", qlItem.getQLId());
        if (getParent() == null) {
            setResult(Activity.RESULT_OK, data);
        }
        else {
            getParent().setResult(Activity.RESULT_OK, data);
        }
    }
    finish();
}

Here is my onActivityResult handler:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_QUICKLIST) {
        if (resultCode == Activity.RESULT_OK) {
            Bundle extras = data.getExtras();
            if (extras != null) {
                int id = extras.getInt("ql_id");
                if (id > 0) {
                    launchQLItemsThread(id);
                }
            }
        }
    }
}
like image 607
Andrew Avatar asked Jul 29 '10 21:07

Andrew


People also ask

What is the alternative for startActivityForResult?

In this article, we will discuss the Activity Result API, an alternative to the deprecated startActivityForResult + onActivityResult methods. We will use Kotlin in this article for the code samples. Android introduced the Activity Result APIs as a major change in the androidx.

What is request code startActivityForResult?

The request code is any int value. The request code identifies the return result when the result arrives. ( You can call startActivityForResult more than once before you get any results. When results arrive, you use the request code to distinguish one result from another.


1 Answers

From the documentation of startActivityForResult: "For example, if the activity you are launching uses the singleTask launch mode, it will not run in your task and thus you will immediately receive a cancel result." singleInstance activities are the same way.

In other words, if you want to use sAFR, you will need to handle multiple activity instances. What I would advise is storing the list state for your ListActivity instances in onPause to some app-global spot (a singleton or whatever), and loading from there in onResume. Then, even if multiple ListActivity instances will get created, the top one will always update the data before the older ones get resumed, and the lists will always appear current to the user.

Note that you should be doing that anyway if your data is meant to be persistent, because your whole process can be killed by the system any time after an onPause call, and if you haven't saved any changes somewhere by the time that returns, they are liable to get silently lost under some -- often rare and unpredictable -- circumstances. In this case you want to be using local files or SQLite databases, not persisting to the network. onPause needs to return quickly because the user can't interact with the system while it's running, so save to local storage and then sync to the network at some other time, perhaps via a service launched by onPause.

like image 123
Walter Mundt Avatar answered Oct 25 '22 10:10

Walter Mundt