setResult ไม่ทำงานเมื่อกดปุ่ม BACK


111

ฉันกำลังพยายาม setResult หลังจากที่กดปุ่ม BACK ฉันโทรหา onDestroy

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

แต่เมื่อมันมาถึง

onActivityResult(int requestCode, int resultCode, Intent data) 

resultCode คือ 0 (RESULT_CANCELED) และข้อมูลเป็น 'null'

ดังนั้นฉันจะส่งผลลัพธ์จากกิจกรรมที่ยกเลิกโดยปุ่ม BACK ได้อย่างไร?

คำตอบ:


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.onBackPressed () จะต้องเกิดขึ้นหลังจากการเรียก setResult () ตามที่แสดงด้านบนมิฉะนั้นคุณจะมีปัญหาเดิมอีกครั้ง!
jengelsma

1
นั่นเป็นคำตอบที่ดีที่สุดที่นี่ หากเราแทนที่ onPause () หรือ onDestroy () onBackPressed () จะถูกเรียกก่อนและจะตั้งค่าผลลัพธ์เป็น 0 โปรดระวัง!
Marek

หรือคุณสามารถตั้งค่าผลลัพธ์เริ่มต้นใน onCreate สถานที่ใด ๆ ก่อนที่จะเสร็จสิ้น () ไม่เป็นไร
Helin Wang

5
ฉันใช้แนวทางที่คล้ายกัน แต่ก็ยังไม่ได้ผล FOr อินสแตนซ์ฉันมีรหัสคำขอและความตั้งใจทำงาน แต่ 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 requestCode ผิดใน onActivityResultonOptionsItemSelected()


สิ่งนี้ใช้ได้ในกรณี OPs แต่ไม่ใช่โดยทั่วไปใช่ไหม? มีวิธีการมากกว่า 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เลย


สิ่งนี้ใช้ไม่ได้กับฉันเนื่องจากข้อมูลของฉันได้รับการอัปเดตใน "onPause"
Bostone

หากกิจกรรมของคุณถูกสร้างขึ้นใหม่หลังจากที่คุณโทรsetResult()ข้อมูลของคุณจะหายไป
Jarett Millard

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

อ้างอิงถึงActivityResult (int, int, Intent) doc

วิธีการแก้ปัญหาคือการตรวจสอบresultCodeสำหรับค่าActivity.RESULT_CENCELED ถ้าใช่แสดงว่ามีการกด BACK หรือกิจกรรมขัดข้อง หวังว่ามันจะเหมาะกับพวกคุณนะเหมาะกับฉัน :)


นี่คือวิธีแก้ปัญหาที่แน่นอน .. คุณต้อง Result Code .. ไม่มีใครกำหนดผลลัพธ์ได้นอกจากคุณในโค้ด ดังนั้นหากผลลัพธ์ไม่ตกลงหมายความว่ากดย้อนกลับหรือล้มเหลว ..
ยอห์น

0

onDestroyสายเกินไปในห่วงโซ่ - แทนที่onPauseและตรวจสอบisFinishing()เพื่อตรวจสอบว่ากิจกรรมของคุณสิ้นสุดวงจรชีวิตหรือไม่


1
ไม่นี่ก็สายเกินไปเช่นกัน
alex2k8

ที่จริงผมโทรหาข้อผิดพลาดนี้: code.google.com/p/android/issues/detail?id=1671 ในแอปพลิเคชันที่ซับซ้อนฉันคิดว่าเนื่องจากมีพฤติกรรมบางอย่างที่คุณไม่สามารถตั้งโปรแกรมได้
pjv

นอกจากนี้ยังตอบโต้ได้ง่ายมาก มากจนฉันยังคงทำผิดเหมือนเดิมตลอดระยะเวลา 2 ปีที่ผ่านมาแล้ว
pjv

ที่จริง - นี่มันยิ่งแย่กว่านั้น และมีอยู่ใน JB ขณะที่ฉันกำลังเขียนโค้ด ถ้าฉันเรียกใช้ setResult จาก onPause จะถูกเรียกใช้งาน แต่จะมีการตั้งค่า resultCode ต่ำกว่าหรือข้อมูลเมื่อดำเนินการ onActivityReturn ทำไม?
Bostone

และนั่นเป็นเหตุผลว่า: "การใช้งานวิธีนี้ (onPause) ต้องรวดเร็วมากเพราะกิจกรรมถัดไปจะไม่กลับมาทำงานต่อจนกว่าวิธีนี้จะส่งคืน" goo.gl/8S2Y
Bostone


0

อย่าพึ่งพาตรรกะใด ๆ ที่ดำเนินการใน onPause of one activity เมื่อคุณกลับไปที่จุดเริ่มต้น ตามเอกสาร:

การใช้งานเมธอดนี้ (onPause) ต้องรวดเร็วมากเพราะกิจกรรมถัดไปจะไม่กลับมาอีกจนกว่าเมธอดนี้จะกลับมา

ดูรายละเอียดhttp://goo.gl/8S2Y

วิธีที่ปลอดภัยที่สุดคือตั้งค่าผลลัพธ์หลังจากการดำเนินการแก้ไขผลลัพธ์แต่ละครั้งเสร็จสมบูรณ์ (ตามที่คุณกล่าวไว้ในคำตอบของคุณ)


0

ฉันวางคำตอบอาจจะเป็นประโยชน์กับคนอื่น ๆ : เมื่อตั้งค่า launcheMode ด้วย 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. 
 */
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.