setResult не работает при нажатии кнопки НАЗАД

111

Я пытаюсь установить результат после нажатия кнопки НАЗАД. Я звоню на Дестрой

Intent data = new Intent();
setResult(RESULT_OK, data) 

Но когда дело доходит до

onActivityResult(int requestCode, int resultCode, Intent data) 

resultCode равен 0 (RESULT_CANCELED), а данные - «null».

Итак, как я могу передать результат действия, прекращенного кнопкой НАЗАД?

alex2k8
источник

Ответы:

159

Вам нужно переопределить onBackPressed()метод и установить результат до вызова суперкласса, т.е.

@Override
public void onBackPressed() {
    Bundle bundle = new Bundle();
    bundle.putString(FIELD_A, mA.getText().toString());
    
    Intent mIntent = new Intent();
    mIntent.putExtras(bundle);
    setResult(RESULT_OK, mIntent);
    super.onBackPressed();
}
n224576
источник
23
Обратите внимание: если вы используете этот подход, вызов super.onBackPressed () должен произойти после вызова setResult (), как показано выше, иначе у вас снова возникнет исходная проблема!
jengelsma
1
Это лучший ответ здесь. Если мы переопределим onPause () или onDestroy (), onBackPressed () будет вызван первым и установит результат равным 0. Помните об этом!
Marek
или вы можете установить результат по умолчанию в onCreate. Любое место до finish () подойдет.
Helin Wang
5
Я реализовал аналогичный подход, но он все еще не работает. Для экземпляра у меня есть код запроса и намерение работать, но resultCode всегда равен 0.
Neon Warge
68

Activityрезультат должен быть установлен перед finish() вызовом. Нажатие НАЗАД фактически вызывает finish()ваш вызов activity, поэтому вы можете использовать следующий фрагмент:

@Override
public void finish() {
    Intent data = new Intent();
    setResult(RESULT_OK, data); 

    super.finish();
}

Если вы звоните NavUtils.navigateUpFromSameTask();в onOptionsItemSelected(), finish()называется, но вы получите неправильно result code. Таким образом , вы должны позвонить finish()не navigateUpFromSameTaskв onOptionsItemSelected(). неправильный код запроса в onActivityResult

JBM
источник
Это работает в случае OP, но не в целом, верно? Есть больше методов, чем finish (), которые вызывают конец жизненного цикла приложения (через onPause () и onDestroy ())? Также см. Мой комментарий к другому ответу.
pjv
И даже если бы его не было, вы бы не узнали об этом, когда он будет представлен в обновлении API. Не так легко, как если бы изменилось поведение onPause () или onDestroy (). Это методы, которые вы должны переопределить.
pjv
6
@pjv - Я не понимаю вашу точку зрения, то , что finishнужно делать с onPauseи onDestroy? Они совершенно не связаны, за исключением того, что finishзапускает процесс завершения , частью которого onPauseи onDestroyявляется.
JBM
20

Если вы хотите установить некоторые пользовательские RESULT_CODEв onBackPressedслучае , то вам необходимо сначала установить , resultа затем вызвать , super.onBackPressed()и вы получите то же самое RESULT_CODEв деятельности вызывающего абоненте onActivityResultметоды

    @Override
    public void onBackPressed()
    {
         setResult(SOME_INTEGER);
         super.onBackPressed();
    }
Хуррам Шехзад
источник
10

Я реорганизовал свой код. Изначально я подготовил некоторые данные и установил их как activity resultв onDestroy(это не сработало). Теперь я устанавливаю activityданные каждый раз, когда возвращаемые данные обновляются и ничего не получаю onDestroy.

alex2k8
источник
У меня это не работает, так как мои данные обновляются в "onPause"
Бостон
Если после звонка ваша активность будет восстановлена setResult(), ваши данные будут потеряны.
Джаретт Миллард,
3

Вы должны переопределить onOptionsItemSelected следующим образом:

@Override
public boolean onOptionsItemSelected(final MenuItem item) {
    switch (item.getItemId()) {
    case android.R.id.home:
        final Intent mIntent = new Intent();
        mIntent.putExtra("param", "value");
        setResult(RESULT_OK, mIntent);
        finish();
        return true;
    default:
        return super.onOptionsItemSelected(item);
    }
}
mdolanci
источник
2

обращаться onActivityResult (int, int, Intent)

Решение - проверить resultCode на значение Activity.RESULT_CENCELED . Если да, то это означает, что либо была нажата НАЗАД, либо действие завершилось сбоем. Надеюсь, это сработает для вас, ребята, работает для меня :).

Анкур
источник
Это точное решение .. У вас должен быть код результата. Никто не может установить результат, кроме вас, в коде. Итак, если результат неудовлетворительный, значит, либо его спина давит, либо он разбился.
Джон
0

onDestroyслишком поздно в цепочке - вместо этого переопределите onPauseи isFinishing()проверьте, находится ли ваша активность в конце своего жизненного цикла.

Роман Нурик
источник
1
Нет, это тоже слишком поздно.
alex2k8
На самом деле я называю это ошибкой: code.google.com/p/android/issues/detail?id=1671 . Я думаю, что в сложных приложениях из-за этого есть просто поведение, которое нельзя запрограммировать.
pjv
Это тоже очень нелогично. Настолько много, что я продолжаю совершать ту же ошибку уже на протяжении двух лет.
pjv
На самом деле - это еще хуже. И он существует в JB, когда я кодирую. Если я вызываю setResult из onPause, он выполняется, но при выполнении onActivityReturn не устанавливается ни код результата, ни данные. Зачем?
Bostone
И вот почему: «Реализации этого метода (onPause) должны быть очень быстрыми, потому что следующее действие не будет возобновлено, пока этот метод не вернет» goo.gl/8S2Y
Bostone
0

Не полагайтесь на какую-либо логику, выполняемую в onPause одного действия, когда вы вернетесь к исходному. Согласно документам:

Реализации этого метода (onPause) должны быть очень быстрыми, потому что следующее действие не будет возобновлено, пока этот метод не вернет

См. Http://goo.gl/8S2Y .

Самый безопасный способ - установить результат после завершения каждой операции изменения результата (как вы упомянули в своем ответе)

Bostone
источник
0

Я вставляю ответ, может быть, будет полезен другим людям: когда установлен режим запуска с android: launchMode = "singleTask", я также не могу получить результат, в документе говорится:

     /* <p>Note that this method should only be used with Intent protocols
 * that are defined to return a result.  In other protocols (such as
 * {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may
 * not get the result when you expect.  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.
 */

и:

     /* <p>As a special case, if you call startActivityForResult() with a requestCode 
 * >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your
 * activity, then your window will not be displayed until a result is 
 * returned back from the started activity.  This is to avoid visible 
 * flickering when redirecting to another activity. 
 */
Banxi1988
источник