액티비티에서 프레그먼트를 접근하는 방법은 아랫처럼, FragmentManager.findFragmentBy를 통해
val fragment: ExampleFragment =
supportFragmentManager.findFragmentById(R.id.fragment_container) as ExampleFragment
해당 프레그먼트가 존재하는 걸 확인한 다음에 프레그먼트에 있는 멤버에 접근할 수 있습니다.
님의 경우에는 이 방법이 권장해도 되는 방법인지 아닌지 모르겠네요. 이유는 프레그먼트에서 실행하는 쓰레드 때문인데요, 쓰레드를 사용할 때는 라이프사이클 등을 주의해서 코드를 짜셔야 합니다. 현재 쓰레드가 무한루프를 도는데, 만약에 앱이 백그라운드로 가게 되더라도 쓰레드는 쓸데없이 계속 돌게 될 것으로 보이구요, 해당 프레그먼트가 종료되었을 경우에도 쓰레드가 종료되지 않고 남아 있을 것 같은 생각이 드네요. 이렇게 되면 결국 메모리 누수가 나게 되고 문제가 생깁니다.
그리고 쓰레드 안에서 Thread.sleep를 사용하셨는데, 이 메소드는 blocking이라 UI를 얼게 만들기 때문에 사용하지 말라고 하는 메소드 중의 하나입니다. 쓰레드 대신에 Timer 같은 클래스를 고려해 보시는 것도 좋을 것 같습니다.
그리고 가능하다면, UI와 관련된 로직은 UI로부터 분리해서 작성하는게 일반적인 원칙입니다. 그리고 observer 패턴을 사용하면 이벤트가 발생할 때 알 수 있으므로 굳이 액티비티가 프레그먼트의 메소드를 직접 액세스할 필요성이 없어지거나 확 줄어듭니다.
public class CallTimer {
public interface Listener {
void onStarted();
void onStopped();
void onProgress(String callTime);
}
private final Set<Listener> listeners = new HashSet<>();
public void addListener(Listener listener) {
listeners.add(listener);
}
public void removeListener(Listener listener) {
listeners.remove(listener);
}
public void start() {
// 쓰레드 로직. 쓰레드 안에서 lisetner.onProgress() 호출
for (Listener listener : listeners) {
lisetner.onStarted();
}
}
public void stop() {
for (Listener listener : listeners) {
lisetner.onStopped();
}
}
// Singleton이 필요할 경우 생성자를 private로 만들고 getInstance() 메소드를 사용.
public static CallTimer getInstance() {
return Impl.INSTANCE;
}
private static class Impl {
private CallTimer INSTANCE.= new CallTimer();
}
}
// Activity
public void onStart(...) {
super.onStart(..)
CallTimer.getInstance().start();
}
public void onStop(...) {
super.onStop(..)
CallTimer.getInstance().stop();
}
// Fragment
public ExampleFramment implements CallTimer.Lsitener {
public void onStart(...) {
super.onStart(...);
CallTimer.getInstance().addListener(this);
}
public void onStop(...) {
super.onStop(...);
CallTimer.getInstance().removeListener(this);
}
// CallTimer.Lsitener 메소드 구현 생략
}
위처럼 Call timer를 처리하는 클래스를 하나 만들고 observer를 등록해서 시간변경에 대한 이벤트를 받을 수 있을 것 같고, 액티비티와 프레그먼트 간에 동일한 인스턴스를 공유하면 액티비티가 프레그먼트에 직접 접근하지 않아도 될 것 같습니다.
위의 코드가 기본적인 아이디어이니 참고하셔서 개선된 구조를 가져가시기 바랍니다.