startActivityForResult не работает должным образом с launchMode singleInstance - PullRequest
18 голосов
/ 30 июля 2010

Я бы хотел, чтобы действия в стеке действий моего приложения имели только один экземпляр. У меня есть несколько экранов ListActivities, и я бы не хотел испытывать трудности и страдания от обновления списков в предыдущем экземпляре ListActivity, когда другой экземпляр этого ListActivity изменен (добавлен, отредактирован, удален и т. Д.) (или есть простой способ сделать это?).

Примечание: я читал, что singleTop выполнит это (хотя он уничтожит активность, если вы нажмете кнопку назад), но он не работает. У меня есть меню, и если я перехожу на экран «Входящие», я перехожу на экран «QuickList», а затем снова на экран «Входящие», он создает новое действие «Входящие».

Прямо сейчас в моих ListActivities у меня для launchMode установлено значение singleInstance. Проблема заключается в следующем: если я запускаю другое действие с помощью startActivityForResult, обработчик onActivityResult запускается сразу (до создания нового действия). Когда я выполняю необходимое действие на следующем экране для возврата результата, обработчик onActivityResult не запускается.

Что происходит?

Вот как я запускаю новую активность:

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

Вот как я возвращаю результат:

@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();
}

Вот мой обработчик onActivityResult:

@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);
                }
            }
        }
    }
}

Ответы [ 2 ]

24 голосов
/ 30 июля 2010

Из документации startActivityForResult: «Например, если запускаемое вами действие использует режим запуска singleTask, оно не будет выполняться в вашей задаче и, следовательно, вы сразу получите результат отмены». singleInstance действия одинаковы.

Другими словами, если вы хотите использовать sAFR, вам нужно будет обрабатывать несколько экземпляров активности. Я бы посоветовал сохранить состояние списка для ваших ListActivity экземпляров в onPause в каком-то глобальном месте приложения (одиночном или любом другом) и загрузить оттуда в onResume. Затем, даже если будет создано несколько ListActivity экземпляров, верхний всегда будет обновлять данные до возобновления старых, а списки всегда будут отображаться для пользователя.

Обратите внимание, что вы должны делать это в любом случае, если ваши данные должны быть постоянными, потому что весь процесс может быть уничтожен системой в любое время после вызова onPause, и если вы не сохранили какие-либо изменения с помощью время, которое возвращается, они могут молча потеряться при некоторых - часто редких и непредсказуемых - обстоятельствах. В этом случае вы хотите использовать локальные файлы или базы данных SQLite, не сохраняя их в сети. onPause необходимо быстро вернуть, поскольку пользователь не может взаимодействовать с системой во время ее работы, поэтому сохраните ее в локальном хранилище и затем синхронизируйте с сетью в другое время, возможно, через службу, запущенную onPause.

2 голосов
/ 30 июля 2010

У меня есть несколько экранов, которые ListActivities и я бы не хотел идти через боль и страдания обновление списков в предыдущем Экземпляр ListActivity, когда другой экземпляр этой ListActivity изменен (или есть простой способ сделать это?).

Используйте последовательную модель. Например, ваши данные, надеюсь, находятся в базе данных. Каждый ListActivity имеет Cursor в той части базы данных, которая ему нужна. Пусть Cursor будет «управляемым курсором» (через startManagingCursor()), и ваш ListViews автоматически обновится в onResume(). Затем вы вносите изменения в модель через базу данных.

У меня есть меню, и если я иду в папку «Входящие» экран, затем я иду в свой QuickList экран, а затем я иду в свой почтовый ящик снова экран, он создает новый почтовый ящик Активность.

Вот что он должен делать. Цитирование документации :

Режимы "стандартный" и "одиночный" отличаются друг от друга только одним уважение: каждый раз, когда есть новое намерение за "стандартную" деятельность, новый Экземпляр класса создан для ответить на это намерение. Каждый экземпляр обрабатывает единственное намерение. Точно так же, новый экземпляр активности "singleTop" также может быть создан для обработки нового намерение. Однако, если целевая задача уже есть существующий экземпляр активность на вершине своего стека, этот экземпляр получит новый намерение (в вызове onNewIntent ()); новый экземпляр не создан. В другие обстоятельства - например, если существующий экземпляр активность "singleTop" находится в цели задача, но не на вершине стека, или если это на вершине стека, но не в целевой задаче - новый экземпляр будет создан и помещен в стеке.

(жирный шрифт добавлен для выделения)

Прямо сейчас в моих ListActivities у меня для launchMode установлено значение singleInstance.

Пожалуйста, не делайте этого.

...