Fragment에 extends 에 대한 추가 질문

조회수 690회
public abstract class AbstractDataInterface : DataInterface 
{
    public static int SEND_TO_LAYER1 = 0, SEND_TO_LAYER2 = 1, SEND_TO_LAYER3 = 2, SEND_TO_LAYER4 = 3, SEND_TO_DATA = 4, SEND_TO_PROC = 5;
    public static int
            IDX_LAYER_DISP_BASE = 0,    // IDX_LAYER1 = 0
            IDX_LAYER_DISP_MASK = 1,    // IDX_LAYER2 = 1
            IDX_LAYER_DISP_CHAR = 2,    // IDX_LAYER3 = 3
            IDX_LAYER_DISP_MENU = 3,    // IDX_LAYER4 = 4
            IDX_PROCS_DISP_DATA = 4,
            IDX_PROCS_DISP_PROC = 5;
    public static int MAX_HANDLER = 6;
    public static Handler[] _Handler = new Handler[MAX_HANDLER];

    public abstract void SetHandler(int dest, Handler handler);
    public abstract Handler GetHandler(int dest);
    public abstract int SendMessage(Handler handler, int dest, int cmd, Object o);

    public abstract void onDestroy();

}

interface DataInterface
{
}

public class Main_Menu_Fragment : Fragment, Activitys.AbstractDataInterface
{
    Button _btnGeneral, _btnAIS, _btnSAT, _btnNotices, _btnRAP, _btnFiles, _btnMap, _btnUnits, _btnFF, _btnFace, _btnRD, _btnIS;
    FragmentTransaction _Main_Fragment;
    Main_Title_Fragment _Text_Change;

    public override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        // Create your fragment here
    }

    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View Main_Menu = inflater.Inflate(Resource.Layout.Main_Menu_Layout, container, false);

        return Main_Menu;
    }

이런식으로 이루어진 3개의 클래스 파일입니다, 전 질문에서 말한 abs는 맨 위에 나와있는 인터페이스를 말하는거구요. 이 상태에서 플래그먼트에서 abs 인터페이스를 참조하려면 어떻게 해야할까요?ㅠ

  • (•́ ✖ •̀)
    알 수 없는 사용자

2 답변

  • DataInterface 가 어떤 의도로 작성 된 것인지는 잘 모르겠지만 아래와 같이 작성 해 볼 수 있습니다.

    DataManipulableFragment

    abstract class DataManipulableFragment extends Fragment {
        public static int SEND_TO_LAYER1 = 0, SEND_TO_LAYER2 = 1, SEND_TO_LAYER3 = 2, SEND_TO_LAYER4 = 3, SEND_TO_DATA = 4, SEND_TO_PROC = 5;
        public static int
                IDX_LAYER_DISP_BASE = 0,    // IDX_LAYER1 = 0
                IDX_LAYER_DISP_MASK = 1,    // IDX_LAYER2 = 1
                IDX_LAYER_DISP_CHAR = 2,    // IDX_LAYER3 = 3
                IDX_LAYER_DISP_MENU = 3,    // IDX_LAYER4 = 4
                IDX_PROCS_DISP_DATA = 4,
                IDX_PROCS_DISP_PROC = 5;
        public static int MAX_HANDLER = 6;
        public static Handler[] _Handler = new Handler[MAX_HANDLER];
    
        public abstract void setHandler(int dest, Handler handler);
    
        public abstract Handler getHandler(int dest);
    
        public abstract int sendMessage(Handler handler, int dest, int cmd, Object o);
    
        public abstract void destroy();
    }
    

    MainMenuFragment

    public class MainMenuFragment extends DataManipulableFragment {
        @Override
        public void setHandler(int dest, Handler handler) {
    
        }
    
        @Override
        public Handler getHandler(int dest) {
            return null;
        }
    
        @Override
        public int sendMessage(Handler handler, int dest, int cmd, Object o) {
            return 0;
        }
    
        @Override
        public void destroy() {
    
        }
    }
    

    그런데 Handler[] 를 static 으로 선언해서 쓰시려는 것을 보면 그것이 좋고 나쁜 방법임을 떠나서 무언가 중계 역할을 하는 클래스를 작성하시려고 하는게 아닌가 싶기도 하네요.

    • (•́ ✖ •̀)
      알 수 없는 사용자
    • Handler가 중계역할을 하는 건 맞습니다. 그런데 올려주신데로라면, 기본의 Activity는 그대로 두고, 새로운 Fragment를 만들어서 저런식으로 하는건가요? 상속받는 애들이 Fragment 만 있는 게 아니라 다른 Activity에서도 abs 를 상속받고 있는 상황이라.. 알 수 없는 사용자 2018.8.10 14:58
    • Singleton 패턴의 클래스를 작성하거나, 위에서 Fragment 에 대응하기 위해 Fragment 를 extends 한 abstract class 를 작성하였듯이 Activity 에 대응하기 위한 abstract class 를 만드는 방법도 있습니다. 단순히 참조만 생각한다면 이외에도 방법은 여러가지가 있을 수 있습니다. 해당 클래스가 하는 역할과 목적에 따라 좋은 구조를 찾아야 할것 같네요 :) 이에대해 추가 댓글을 달아주시면 좀더 도움을 드릴 수 있을 것 같습니다 알 수 없는 사용자 2018.8.10 16:39
    • 하는 역할이라고 해야할까, 일단 Activity가 참조하는 클래스와 Fragment가 참조하는 클래스는 동일한 이벤트를 가지고 있구요, Fragment는 흔히말하는 메뉴들의 이벤트를 받아서 interface에 연결하는 음.. MVP 모델을 기반으로 하는 걸 만드려고 하는건데..흠 어찌 설명해야할지 감이 안오네요 ㅠ 알 수 없는 사용자 2018.8.10 16:46
    • 각 이벤트의 delegate, 즉 실제 이벤트를 실행 하는 주체는 Activity 와 Fragment 에 구현되어지나요? 알 수 없는 사용자 2018.8.10 18:25
    • 네, 이벤트 자체는 Activity와 Fragment에서 구현되고, 그걸 abs측에서 처리하는? 모양입니다. 알 수 없는 사용자 2018.8.10 18:33
    • 음.. 예를 좀 들어주실수 있을까요? 어떤 이벤트 들이 있고, 이것을 DataInterface 와 어떤 연계작업을 하는지.. 흐름적으로 좀더 디테일한 내용이 필요 한 것 같습니다 알 수 없는 사용자 2018.8.11 10:36
    • 메뉴에 대한 이벤트에요, 예를 들어 화면을 껏다 킨다 라는 이벤트가 있다면 그 이벤트를 받아서 넘겨주는 거죠...? 제가 설명하는게 좀 딸려서 어찌 설명을 드려야할지 감이 안잡히네요 ㅠ 알 수 없는 사용자 2018.8.13 08:52
    • 플래그먼트에서 A라는 항목의 이벤트로 Switch를 넣었다하면 플래그먼트A에서 이 Switch의 ON,OFF 이벤트를 B라는 액티비티로 interface를 이용해서 보내서고 싶은거에요. 알 수 없는 사용자 2018.8.13 10:01
    • B라는 액티비티에는 SetHandler 등등의 이벤트가 있고, 이걸 플래그먼트에서 참조하여 사용하고 싶다라는건데... 다른 액티비티는 이제 자마린 같은 경우 ":"를 사용하여 implements 하면 사용할 수 있지만 플래그먼트에서는 이미 참조하고 있는 class가 있기에 불가능하더라구요. 이걸 interface라면 가능하다고 하시는건데 그 방법이 자세히 모르겠어요 ㅠ 알 수 없는 사용자 2018.8.13 10:03
  • 정확한 상황이 파악이 되질 않지만 도움이 되실지 모르겠지만 추가 예제 코드를 올려봅니다.

    Fragment 의 Swtich 에 대한 값을 받아서 무언가 이벤트를 처리 하려고 Activity 에 (MainActivity.java) 아래와 같은 메소드를 작성했다고 가정해보면,

    public void changedSwitchValue(boolean value) {
        //do something
    }
    

    Fragment 에서는 아래와 같이 호출하여 사용 할 수 있을 것입니다.

    ((MainActivity) getActivity()).changedSwitchValue(switch.isChecked());
    

    그런데 만약 switch 값 변경에 대한 이벤트를 받아 처리해야 할 클래스들이 여러개라면 다음과 같이 interface 를 사용 해 볼 수도 있습니다.

    public interface OnSwitchChangedListener {
        void changedSwitchValue(boolean value);
    }
    

    TestFragment.java

    public class TestFragment extends Fragment {
        private List<OnSwitchChangedListener> mListeners = new ArrayList<>();
        ....
    
        @Override
        public void onActivityCreated(@Nullable Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            mSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    dispatchSwitchChangedEvent(isChecked);
                }
            });
        }
    
        public void addOnSwitchChangedListener(OnSwitchChangedListener listener){
            if(!mListeners.contains(listener)) mListeners.add(listener);
        }
    
        public void removeOnSwitchChangedListener(OnSwitchChangedListener listener){
            mListeners.remove(listener);
        }
    
        private void dispatchSwitchChangedEvent(boolean isChecked){
            for(OnSwitchChangedListener l : mListeners){
                l.changedSwitchValue(isChecked);
            }
        }
    }
    

    이렇게 하면 TestFragment 의 switch 값에 변경 이벤트를 얻고 싶은 클래스에서 OnSwitchChangedListener 를 구현한 뒤 addOnSwitchChangedListener() 를 통해 listener 를 등록하여 사용 할 수 있습니다.

    • (•́ ✖ •̀)
      알 수 없는 사용자
    • Activity와 Fragment 사이에 interface를 놓는 방법이 있다고 하셨잖아요? 그 방법은 어떤식으로 사용해야하나요? 알 수 없는 사용자 2018.8.13 17:24
    • Activity 와 Fragment 사이에 interface 를 놓는다. 라는 말을 하진 않았습니다만.. ㅠㅠ AbstractDataInterface 가 추상 클래스로 짜놓으신거 보면 저 클래스를 extends 하여 뭔가 이벤트 주체가 되는 클래스를 작성하시려는 것 같은데 정확한 의도를 잘 모르겠습니다 ㅜㅜ 아니면 제 인스타 계정으로 dm 을 주시겠어요? 알 수 없는 사용자 2018.8.13 18:05
    • 음, 방금 해결했습니다! 말씀해주신거랑 좀 다르게 해결했지 AbstarctDataInterface가 다중 상속이 가능한 녀석이라 거기에 Fragment 상속하고 Fragment에는 Abs를 상속했어요! 그러니까 해결은 되더라구요! 다중 상속을 생각못하고 있었어요 ㅠㅠㅠ 알 수 없는 사용자 2018.8.13 18:41
    • 아 첫번째 답변드린 방식인가요? 해결되셔서 다행이네요 :) 알 수 없는 사용자 2018.8.13 19:16
    • 네, 제가 말씀하신 첫번째 방법 이해를 제대로 못한거더라구요 ㅠㅠ 감사합니다! 알 수 없는 사용자 2018.8.13 19:43
    • 다행입니다!! 즐거운 개발되세요!! 알 수 없는 사용자 2018.8.13 20:03
    • 다음번에도 부탁드립니다?!ㅋㅋ 알 수 없는 사용자 2018.8.13 20:55

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)