박상권의 삽질블로그

[안드로이드/Android]Fragment에서 Activity의 onActivityForResult 받는 방법 본문

IT/Android-TIP (한글)

[안드로이드/Android]Fragment에서 Activity의 onActivityForResult 받는 방법

박상권 2015. 11. 30. 18:43

안드로이드 개발자들이 모여있는 오픈채팅방에 참여해보세요 .
Q&A 및 팁을 공유하는 방입니다..
오픈채팅방 참여



블로그를 Medium으로 옮겨서 운영하고 있습니다.
앞으로 새로운 글은 모두 미디엄 블로그를 통해서 올릴 예정입니다.
미디엄에서 다양하고 유익한 포스팅을 살펴보세요
미디엄 블로그 보기



Fragment를 사용하면서 startActivity나 startActivityForResult를 사용하는 경우가 있습니다.

startActivity가 문제되는경우는 없지만 startActivityForResult에서 가끔 onActivityResult가 오지 않는 경우가 있습니다.

Nested Fragment구조로 되어있는 Fragment에서는 startActivirtyForResult의 결과가 Fragment가 아닌 Activity로 오게 됩니다.


Activity에 넘어온 결과를 Fragment로 넘겨주기위하여 Fragment내부에 함수를 만들어 해당 instance의 함수를 호출하거나 static 함수로 만들어두어 해당 함수를 호출하곤 하는데요.

이와 비슷한 방식이지만 event bus방식의 otto를 사용해서 좀더 심플하고 직관적으로 구현해보도록 하겠습니다.


[안드로이드]유용한 라이브러리 - Otto(Event Bus)






동작순서


- 부모 Activity에서 Fragment로 알려줄 Event클래스를 생성합니다.

- Fragment에서 Event를 받았을때 실행할 함수를 만들어 두고 해당 Event를 모니터링합니다.

- Fragment에서 startActivityForResult()를 호출합니다.

   (이때 Fragment의 startActivityForResult를 실행하는것이 아닌 부모 Activity의 startActivityForResult를 실행해야 합니다)

- 실행된 Activity가 종료되면서 Fragment의 부모 Activity로 결과값을 리턴해줍니다

- 결과를 받은 Activity에서 Event를 생성해서 Fragment로 알려주면서 결과값을 보내줍니다.

- Fragment는 해당 Event를 받아서 1번에서 만들어준 동작을 수행합니다.








Fragment에서 Activity의 onActivityForResult 받기



1. Event Class생성


onActivityResult의 parameter들을 그대로 받아서 Fragment로 넘겨주기위해 해당 값들을 가지고 있는 Event Class를 생성해줍니다.

 


public class ActivityResultEvent {

private int requestCode;
private int resultCode;
private Intent data;

public ActivityResultEvent(int requestCode, int resultCode, Intent data) {
this.requestCode = requestCode;
this.resultCode = resultCode;
this.data = data;
}

public int getRequestCode() {
return requestCode;
}

public void setRequestCode(int requestCode) {
this.requestCode = requestCode;
}

public int getResultCode() {
return resultCode;
}

public void setResultCode(int resultCode) {
this.resultCode = resultCode;
}

public Intent getData() {
return data;
}

public void setData(Intent data) {
this.data = data;
}
}










2. Event 함수 생성 및 모니터링


1번에서 만들어둔 Event를 받았을때 실행할 함수를 만들어 줍니다.

저같은 경우는 Fragment의 onActivityResult로 데이터들을 바로 넘겨주는 방식으로 구현해 두었습니다.

onActivityResult함수에서 받은 결과값을 가지고 동작을 해줍니다.



/**
* NestedFragment에서 startactivityForresult실행시 fragment에 들어오지 않는 문제
*
* @param activityResultEvent
*/
@Subscribe
public void onActivityResult(ActivityResultEvent activityResultEvent){
onActivityResult(activityResultEvent.getRequestCode(), activityResultEvent.getResultCode(), activityResultEvent.getData());
}




또한, 이 Event를 받기위해서 register/unregister작업을 해주어야 합니다.

저는 BaseFragment를 만들어두고 거기에 register/unregister작업을 해둔뒤 모든 Fragment가 이 BaseFragment를 상속받아서 사용하도록 해두고 있습니다.

그렇게 만들어두면 Fragment를 생성할때마다 귀찮은 작업을 해주는걸 줄일 수 있습니다.



@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
BusProvider.getInstance().register(this);
}

@Override
public void onDestroyView() {
BusProvider.getInstance().unregister(this);
super.onDestroyView();

}




3. Fragment에서 startActivityForResult 함수 실행



startActivityForResult함수를 실행할때 주의할점은 Fragment의 함수가 아닌  Activity의 함수를 이용해주어야 한다는것입니다.

그래야 부모 Activity에서 결과값을 받았을때 동일한 requestCode값을 받아올 수 있습니다.

그렇지 않은경우 Fragment에서 실행했던 requestCode와 부모Activity에서 받은 requestCode가 달라서 해당 결과값을 받아올수 없는 문제가 발생합니다.


getActivity().startActivityForResult(intent, Constant.REQ_CODE_CONTENT_DETAIL);








4. 부모 Activity에서 Event생성


실행된 Activity가 종료되면 부모 Activity의 onActivityResult가 실행됩니다.

이때 1번에서 만들어둔 ActivityResultEvent를 생성해주면서 Fragment에서 이 이벤트를 받을수 있도록 해줍니다.



@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
BusProvider.getInstance().post(new ActivityResultEvent(requestCode, resultCode, data));
}









이렇게되면 2번에서 해당 Event를 받았을때 동작할 함수를 만들어두었기때문에 Fragment에서 일을 처리할 수 있게됩니다.

이를 잘 응용한다면 onBackPressed()이벤트도 충분히 Fragment에서 받아서 처리할 수 있게됩니다.

이뿐만 아니라 여러가지 상황을 간단하게 otto를 활용해서 구현해보시면 훨씬 간단하고 직관적인 코드를 만드실 수 있습니다.




Comments