setResult не працює при натисканні кнопки НАЗАД


111

Я намагаюся встановити результат після натискання кнопки НАЗАД. Я заходжу в Destroy

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

Але коли справа доходить

onActivityResult(int requestCode, int resultCode, Intent data) 

resultCode дорівнює 0 (RESULT_CANCELED), а дані - "null".

Отже, як я можу передати результат від діяльності, припиненої кнопкою НАЗАД?

Відповіді:


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

23
Зауважте, що якщо ви використовуєте такий підхід, виклик super.onBackPress () повинен відбутися після виклику setResult (), як показано вище, або у вас виникне початкова проблема знову!
jengelsma

1
Тут найкраща відповідь. Якщо ми перекриємо onPause () або onDestroy (), спочатку буде викликано onBackPress (), і це встановить результат 0. Будь ласка, пам’ятайте про це!
Марек

або ви можете встановити результат за замовчуванням у onCreate. Будь-яке місце до фінішу () - чудово.
Хелін Ван

5
Я реалізував подібний підхід, але він все ще не працює. Для першого екземпляра у мене є код запиту, і намір працює, але результатCode завжди є 0.
Неонова 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


Це працює у випадку з ОП, але не загалом, правда? Є більше методів, ніж закінчення (), які спонукають закінчити життєвий цикл програми (через 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.


Це не працює для мене, оскільки мої дані оновлюються в "onPause"
Bostone

Якщо ваша активність буде відтворена після дзвінка 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);
    }
}

2

Зверніться до документу onActivityResult (int, int, Intent)

Рішення полягає в перевірці ResultCode для значення Activity.RESULT_CENCELED . Якщо так, то це означає, що або натискали кнопку BACK, або активність припиняється. Сподіваюся, це працює для вас, хлопці, працює для мене :).


Це точне рішення. Ви повинні Код результату .. Ніхто не може встановити результат, окрім вас, у коді. Отже, якщо результат не в порядку, це означає, що його натискають спиною, або розбивають ..
Іван

0

onDestroyзанадто пізно в ланцюжку - замість цього переосмислюйте onPauseта isFinishing()перевіряйте, чи не закінчується ваша діяльність в кінці її життєвого циклу.


1
Ні, це теж пізно.
alex2k8

Я фактично називаю це помилкою: code.google.com/p/android/isissue/detail?id=1671 . Я думаю, що в складних програмах існує певна поведінка, яку ви не можете запрограмувати.
pjv

Це також дуже контрінтуїтивно. Настільки багато, що я продовжую робити ту саму помилку вже протягом 2 років.
pjv

Власне - це ще гірше. І це існує в JB, як я кодую. Якщо я називаю setResult з onPause, він виконується, але при виконанні onActivityReturn не встановлено більш нікого результату, коду, а також даних. Чому?
Бостон

І тому: "Реалізація цього методу (onPause) повинна бути дуже швидкою, оскільки наступна діяльність не буде відновлена, поки цей метод не повернеться" goo.gl/8S2Y
Bostone

0

Спробуйте переосмислити функцію onBackPress (від рівня Android на 5 вище) або перезавантажте програму onKeyDown () та перейдіть на KeyEvent.BUTTON_BACK (див. Результати діяльності Android ) Це робить для мене хитрість.


0

Не повертайтеся на будь-яку логіку, виконану в onPause однієї діяльності, коли ви повернетесь до початкової. Згідно з документами:

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

Детальну інформацію див. У розділі http://goo.gl/8S2Y .

Найбезпечніший спосіб - встановити результат після завершення кожної операції зі зміни результату (як ви згадуєте у своїй відповіді)


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. 
 */
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.