setResult không hoạt động khi nhấn nút QUAY LẠI


111

Tôi đang cố gắng thiết lập Kết quả sau khi nhấn nút QUAY LẠI. Tôi gọi vào onDestroy

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

Nhưng khi nói đến

onActivityResult(int requestCode, int resultCode, Intent data) 

mã kết quả là 0 (RESULT_CANCELED) và dữ liệu là 'null'.

Vì vậy, làm cách nào tôi có thể chuyển kết quả từ hoạt động bị kết thúc bằng nút QUAY LẠI?

Câu trả lời:


159

Bạn cần ghi đè onBackPressed()phương thức và đặt kết quả trước lệnh gọi đến lớp cha, tức là

@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
Xin lưu ý rằng nếu bạn sử dụng cách tiếp cận này, lệnh gọi super.onBackPressed () phải xảy ra sau lệnh gọi setResult () như được hiển thị ở trên, nếu không bạn sẽ gặp lại sự cố ban đầu!
jengelsma

1
Đó là câu trả lời tốt nhất ở đây. Nếu chúng ta ghi đè onPause () hoặc onDestroy (), onBackPressed () sẽ được gọi đầu tiên và nó sẽ đặt kết quả là 0. Hãy lưu ý điều đó!
Marek

hoặc bạn có thể đặt kết quả mặc định trong onCreate. Bất kỳ chỗ nào trước khi kết thúc () đều được.
Helin Wang

5
Tôi đã thực hiện cách tiếp cận tương tự nhưng nó vẫn không hoạt động. Ví dụ tôi có mã yêu cầu và làm việc ý nhưng resultCode luôn là 0.
Neon Warge

68

Activitykết quả phải được đặt trước khi finish() được gọi. Nhấp vào QUAY LẠI thực sự sẽ gọi đến cuộc gọi finish()của bạn activity, vì vậy bạn có thể sử dụng đoạn mã sau:

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

    super.finish();
}

Nếu bạn gọi NavUtils.navigateUpFromSameTask();vào onOptionsItemSelected(), finish()được gọi, nhưng bạn sẽ nhầm result code. Vì vậy, bạn phải gọi finish()không navigateUpFromSameTaskvào onOptionsItemSelected(). Yêu cầu sai Mã trong onActivityResult


Điều này hoạt động trong trường hợp OP, nhưng không phải nói chung, phải không? Có nhiều phương thức hơn finish () tạo ra sự kết thúc của vòng đời ứng dụng (thông qua onPause () và onDestroy ())? Cũng xem bình luận của tôi ở câu trả lời khác.
pjv

Và ngay cả khi không có, bạn sẽ không biết về nó khi nào nó sẽ được giới thiệu trong bản cập nhật API. Không dễ dàng như bạn làm khi hành vi của onPause () hoặc onDestroy () thay đổi. Đó là những phương thức bạn phải ghi đè.
pjv

6
@pjv - Tôi không hiểu ý bạn, finishphải làm gì với onPauseonDestroy? Những điều đó hoàn toàn không liên quan ngoại trừ điều đó finishbắt đầu quá trình chấm dứt onPauseonDestroylà một phần của.
JBM

20

Nếu bạn muốn đặt một số tùy chỉnh RESULT_CODEtrong onBackPressedtrường hợp thì trước tiên bạn cần đặt resultvà sau đó gọi đến super.onBackPressed()và bạn sẽ nhận được điều tương tự RESULT_CODEtrong onActivityResultphương thức của hoạt động của người gọi

    @Override
    public void onBackPressed()
    {
         setResult(SOME_INTEGER);
         super.onBackPressed();
    }

10

Tôi đã cấu trúc lại mã của mình. Ban đầu, tôi chuẩn bị một số dữ liệu và đặt nó như activity resulttrong onDestroy(điều này không hoạt động). Bây giờ tôi thiết lập activitydữ liệu mỗi khi dữ liệu được trả về được cập nhật và không có gì trong đó onDestroy.


Điều này không làm việc cho tôi từ dữ liệu của tôi là cập nhật trong "onPause"
Bostone

Nếu hoạt động của bạn được tạo lại sau khi bạn gọi setResult(), dữ liệu của bạn sẽ bị mất.
Jarett Millard

3

Bạn nên ghi đè onOptionsItemSelected như thế này:

@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

Tham khảo tài liệu onActivityResult (int, int, Intent)

Giải pháp là kiểm tra mã resultCode cho giá trị Activity.RESULT_CENCELED . Nếu có, thì có nghĩa là BACK đã được nhấn hoặc hoạt động bị lỗi. Hy vọng nó hoạt động cho các bạn, hiệu quả cho tôi :).


Đây là giải pháp chính xác .. Bạn phải Mã Kết quả .. Không ai có thể đặt kết quả ngoài bạn trong mã. Vì vậy, nếu kết quả không OK có nghĩa là nó bị ép ngược hoặc bị va chạm ..
John

0

onDestroyquá muộn trong chuỗi - thay vào đó hãy ghi đè onPausevà kiểm tra isFinishing()để kiểm tra xem hoạt động của bạn có ở cuối vòng đời của nó hay không.


1
Không, điều này là quá muộn.
alex2k8

Tôi thực sự gọi đây là một lỗi: code.google.com/p/android/issues/detail?id=1671 . Trong các ứng dụng phức tạp, tôi nghĩ do điều này có một số hành vi mà bạn không thể lập trình.
pjv

Nó cũng rất phản trực giác. Nhiều đến mức tôi vẫn tiếp tục phạm phải sai lầm tương tự, trong khoảng thời gian 2 năm rồi.
pjv

Trên thực tế - điều này thậm chí còn tồi tệ hơn. Và nó tồn tại trong JB khi tôi đang mã hóa. Nếu tôi gọi setResult từ onPause, nó được thực thi nhưng mã kết quả khác hoặc dữ liệu không được đặt khi onActivityReturn được thực thi. Tại sao?
Bostone

Và đó là lý do tại sao: "Triển khai phương pháp này (onPause) phải rất nhanh chóng bởi vì các hoạt động tiếp theo sẽ không được tiếp tục cho đến nay phương pháp lợi nhuận" goo.gl/8S2Y
Bostone


0

Đừng dựa vào bất kỳ logic nào được thực thi trong onPause của một hoạt động khi bạn quay lại hoạt động ban đầu. Theo tài liệu:

Việc triển khai phương thức này (onPause) phải rất nhanh vì hoạt động tiếp theo sẽ không được tiếp tục cho đến khi phương thức này trả về

Xem http://goo.gl/8S2Y để biết thêm chi tiết.

Cách an toàn nhất là đặt kết quả sau khi mỗi thao tác thay đổi kết quả hoàn tất (như bạn đã đề cập trong câu trả lời của mình)


0

Tôi dán câu trả lời có thể sẽ hữu ích cho những người khác: khi một launcheMode được đặt với android: LauncherMode = "singleTask", tôi cũng không thể nhận được kết quả, tài liệu cho biết:

     /* <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.
 */

và:

     /* <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. 
 */
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.