onActivityResult() ใน Nested Fragment สามารถใช้งานได้แล้วในตัวตั้งแต่ Support Library rev 23.2 เป็นต้นไป

Posted on 26 Mar 2016 19:46 | 8709 reads | 0 shares
 

ปัญหาหนึ่งของ Nested Fragment (Fragment ที่ถูกแปะบน Fragment อีกทีนึง) คือเราสามารถสั่ง startActivityForResult(...) ได้แต่คำสั่ง onActivityResult(...) จะไม่ถูกเรียกเนื่องจากสาเหตุเรื่องของการออกแบบ Fragment หากสนใจสามารถเข้าไปอ่านสาเหตุเต็มๆได้จาก วิธีการทำให้ onActivityResult ของ Nested Fragment ใช้งานได้ในทุกกรณี

ก่อนหน้านี้หากต้องใช้งาน onActivityResult ใน Nested Fragment เราก็ต้องหาวิธีแก้ไขกันไป แต่ล่าสุดบน Android Support Library rev 23.2 ก็มีการแก้ไขครั้งใหญ่ของปัญหาตรงนี้เรียบร้อย เมื่อตอนนี้เราสามารถใช้งาน startActivityForResult และ onActivityResult ได้ทันทีโดยไม่ต้องมาทำอะไรให้วุ่นวายอีกต่อไป!

การทดสอบ

ทดสอบด้วยการสร้าง Fragment ขึ้นมาสองตัว MainFragment และ SecondFragment โดยเอา MainFragment แปะบน Activity และเอา SecondFragment แปะลงบน MainFragment อีกทีหนึ่ง เป็นไปตามรูปด้านล่าง

โดยใน SecondFragment มีการใส่ปุ่มเข้าไปปุ่มนึงคือ btnGo และโค้ดที่ใส่ใน SecondFragment.java เป็นไปตามนี้

// SecondFragment.java

// Calling to SecondActivity
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    ...
    btnGo = (Button) rootView.findViewById(R.id.btnGo);
    btnGo.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(getContext(), SecondActivity.class);
            startActivityForResult(intent, 12345);
        }
    });
}

// Get Result Back
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    Log.d("onActivityResult", "requestCode = " + requestCode);
}

เมื่อมีการกดปุ่ม btnGo จะเห็นว่ามีการเรียกไปยัง SecondActivity ที่มีการ setResult ตามโค้ดด้านล่าง

// SecondActivity.java
public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        Intent intent = new Intent();
        setResult(RESULT_OK, intent);
        finish();
    }
}

ดังนั้นทันทีที SecondActivity ถูกเรียกขึ้นมามันก็จะปิดตัวเองไปพร้อมส่งผลลัพธ์ (Result) กลับทันที

ความคาดหวังคือถ้ามีการกดปุ่ม btnGo คำสั่ง onActivityResult ของ SecondFragment จะต้องถูกเรียก และต้องมี Log ขึ้นมา

ผลการทำงานเป็นแบบนี้

Android Support Library revision 23.1.1

com.inthecheesefactory.lab.nestedfragment I/OpenGLRenderer: Initialized EGL, version 1.4
com.inthecheesefactory.lab.nestedfragment W/EGL_emulation: eglSurfaceAttrib not implemented
com.inthecheesefactory.lab.nestedfragment W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xaf853600, error=EGL_SUCCESS

Android Support Library revision 23.2.1

com.inthecheesefactory.lab.nestedfragment I/OpenGLRenderer: Initialized EGL, version 1.4
com.inthecheesefactory.lab.nestedfragment W/EGL_emulation: eglSurfaceAttrib not implemented
com.inthecheesefactory.lab.nestedfragment W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xaf853600, error=EGL_SUCCESS
com.inthecheesefactory.lab.nestedfragment D/onActivityResult: requestCode = 12345

ก็จะเห็นว่า บน Android Support Library rev 23.1 คำสั่ง onActivityResult บน SecondFragment จะไม่ถูกเรียก ในขณะที่ใน rev 23.2 คำสั่ง onActivityResult ถูกเรียกเรียบร้อยสวยงาม

ถือเป็นการเปลี่ยนแปลงเล็กๆที่ยิ่งใหญ่ จากนี้ไม่ต้องใช้ Workaround อะไรอีกต่อไป สามารถสลับมาใช้ Android Support Library rev 23.2 เป็นต้นไปแทนได้ทันทีครับ โค้ดจะคลีนขึ้นไปอีกขั้น =)

ผู้เขียน: nuuneoi (Android GDE, CTO & CEO at The Cheese Factory)
นักพัฒนาแบบ Full-Stack ที่มีประสบการณ์ในการพัฒนาแอพฯแอนดรอยด์มากว่า 6 ปีและอยู่ในวงการพัฒนาแอพฯมือถือมากว่า 12 ปี มีความสนใจทางด้าน Infrastucture, Service Side, Design, UI&UX, Hardware, Optimization, Cooking, Photographing, Blogging, Training, Public Speaking และรักที่จะแชร์เรื่องราวให้ผู้คนได้อ่านได้ฟังกันผ่าน Blog