반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리

[CookBook] Fragments 이해하기 -7-

2013. 9. 30. 08:47 | Posted by 솔웅


반응형

Implementing Communication Between Fragments



fragment들 사이에서 데이터를 전달할 수 있도록 하기 위해 Fragment 클래스에서는 두개의 메소드를 제공하고 있습니다. 바로 setArguments() 와 getArguments() 인데요. setArguments() 메소드는 fragment의 Bundle을 저장합니다. getArguments() 메소드는 이 전달된 정보를 얻기 위해 Bundle을 retrieve 하죠.



아래 코드는 fragment1에서 fragment2로 정보를 전달합니다. frag2_container는 layout xml 에서 지정한 fragment container의 ID 입니다.



#1 Fragment2Activity fragment2 = new Fragment2Activity();
#2 Bundle args = new Bundle();
#3 String message = "Message from Fragment1";
#4    if(null==fragmentManager.findFragmentByTag(TAG2)){
#5        Fragment2Activity fragment2 = new Fragment2Activity();
#6      args.putString("msg", message);
#7      fragment2.setArguments(args);
#8      fragmentTransaction.replace(R.id.frag2_container,fragment2);
#9        String tag = null;
#10        fragmentTransaction.addToBackStack(tag);
#11        fragmentTransaction.commit();
#12 }



#1에 있는 Fragment2Activity는 fragment2의 자바 클래스를 말합니다. fragment2라는 자바 클래스 인스턴스를 생성했습니다.
#2에서는 args라고 하는 Bundle 객체를 생성했습니다.
#3에서는 message라고 하는 String 객체를 생성했죠. 이 메세지는 fragment2에 전달 될 겁니다.
#4번에서는 TAG2라는 fragment가 있는지 여부를 체크합니다. TAG2는 fragment2를 말하는 거니까 fragment2가 있는지 여부를 체크하는 겁니다.
#5번은 Fragment2Activity 자바클래스의 인스턴스를 만들고 #6번에서는 args 번들에 3번에서 정의했던 메세지를 세팅합니다.
#7에서는 fragment2에 이 Bundle 을 세팅하구요.
#8번과 #9번에서는 이전의 fragment를 navigating하는 부분이구요.



이 activity stack은 이전의 activity들을 계속 track 합니다. Back 버튼을 누르면 activity stack에 있는 activity가 pop up 되서 그 activity 가 화면에 보여지게 됩니다. 다른 말로 이 activity stack은 Back 버튼을 누르면 이전 화면으로 돌아갈 수 있도록 만드는 거죠.



fragment도 이러한 개념을 사용합니다. back stack에 FragmentTransaction을 추가하려면 commit() 하기 전에 FragmentTransaction의 addToBackStack() 메소드를 호출해야 합니다.



위 코드에서 보면 처음에는 xml에 있는 fragment가 화면에 보였다가 두번째 fragment로 replace됐습니다. 그리고 이전 fragment는 BackStack에 넣구요. 그래서 Back 버튼을 누르면 이전의 FragmentTransaction이 돌아와서 이전의 fragment가 화면에 보여질 겁니다.



Bundle을 통해서 위에 setArguments()메세지를 통해 세팅된 정보를 어떻게 다음 fragment에서 이 메세지를 받고 display하는지에 대해서도 궁금할 겁니다. 그 답은 Bundle을 사용해서 fragment에서 메세지를 받는 것은 getArgument() 메소드를 사용한다 입니다.
아래에 샘플 코드가 있습니다.



String messageReceived = "";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    ViewGroup container, Bundle savedInstanceState) {
        Bundle bundle = getArguments();
        if(bundle != null) {
            messageReceived = bundle.getString("msg");
        }
    }
}


fragment끼리의 communication을 이해하기 위해 FragmentsByCodeApp 어플리케이션에서 fragment1에서 fragment 2로 메세지를 보내는 것을 구현하겠습니다. 이를 위해 FragmentsByCodeAppActivity.java 의 코드를 수정합니다.



public class FragmentsByCodeAppActivity extends Activity implements OnOptionSelectedListener {
    private static final String TAG1 = "1";
    private static final String TAG2 = "2";
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragments_by_code_app);
        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        if(null==fragmentManager.findFragmentByTag(TAG1)){
            Fragment1Activity fragment1 = new Fragment1Activity();
            fragmentTransaction.add(R.id.frag1_container, fragment1, TAG1); 
        }
        Bundle args = new Bundle();
        String message="Message from Fragment 1";  

        if(null==fragmentManager.findFragmentByTag(TAG2)){
            Fragment2Activity fragment2 = new Fragment2Activity();
            args.putString("msg", message);
            fragment2.setArguments(args);

            fragmentTransaction.add(R.id.frag2_container, fragment2, TAG2); 
        }
        fragmentTransaction.commit();
        }

    public void onOptionSelected(String msg){
        Fragment2Activity frag2 = (Fragment2Activity) getFragmentManager().findFragmentById(R.id.frag2_container);
        frag2.dispOption(msg);             
    }
}



우선 Bundle 인스턴스인 args를 생성했습니다. 이 args 객체에 message라는 String 객체를 put 했구요. 그리고 이 Bundle을 fragment2에 넣었습니다. 그 다음에 fragment2에서는 이 Bundle 을 getArguments() 메소드를 이용해서 이 정보를 받습니다. 그 받는 부분을 한번 보겠습니다.



public class Fragment2Activity extends Fragment {
    TextView selectedOpt;
    String messageReceived="";


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View vw= inflater.inflate(R.layout.fragment2,  container, false);
           Bundle bundle=getArguments(); 
           if(bundle !=null) {
               messageReceived = bundle.getString("msg");
               selectedOpt = (TextView) vw.findViewById(R.id.selectedopt);
               selectedOpt.setText(messageReceived);
           }
           return vw;     

    }

    public void dispOption(String msg){
        TextView selectedOpt = (TextView) getActivity().findViewById(R.id.selectedopt);
        selectedOpt.setText("You have selected "+msg);  
    }
}


이렇게 getArguments()를 사용해서 해당 정보를 받습니다. 이렇게 받은 정보는 TextView에 뿌려질 거구요.



이 어플리케이션을 실행하면 아래와 같은 화면을 볼 수 있습니다.






Fragment base 클래스 이외에도 fragment는 다른 몇개의 Fragment 클래스의 subclass들을 extend 할 수 있습니다. DialogFragment, ListFragment, PreferenceFragment들이 그것입니다.

반응형


반응형

오늘의 영어 공부는 제가 번역한 글이 아닙니다.

정의와 상식을 추구하는 시민 네트워크에서 번역한 글인데요.


지난 월요일 서울 광장에서 열렸던 천주교의 시국미사에 대한 기사입니다.




독재자 박정희 집권시에 설립된 천주교 정의 구현 사제단이 바티칸 관계자들과 사전 논의를 나눈 한국 주교들의 승인하에 사제들이 현 시국을 '중대한 위기'라고 규정했다고 하는 부분도 있습니다.



Korean Church back in the streets against corrupt intelligence service

한국 가톨릭교회가 부패한 국정원 규탄 위해 다시 거리로 나서다


Seoul Sept 26, 2013: South Korean Catholics are back in the streets to pray and protest against abuses of power and interference by the National Intelligence Service (NIS), South Korea's intelligence service.




2013년 9월 26일, 서울: 한국의 정보기관인 국정원의 권력남용과 정치개입을 규탄하며 시국미사를 올리기 위해 한국 가톨릭 교회가 다시 거리로 나섰다.


On Monday, in front of Seoul City Hall, lay people and members of clergy, including priests and nuns, from across the country shouted slogans and sang songs against the intelligence service and its interference in the lives of ordinary citizens, asking for its dissolution.


지난 월요일 서울 시청 앞, 전국에서 모여든 사제들과 수녀들을 포함한 성직자들, 그리고 시민들이 국정원과 국정원이 평범한 시민의 생활에 개입한 것을 규탄하는 구호를 함께 외치고 노래를 부르며 국정원의 해체를 요구했다.


Among the many cases of abuse, protesters mentioned the last presidential election that ended with the defeat of the United Democratic Party candidate Moon Jae-in, a Catholic, who was also present at the prayer meeting. His defeat was apparently "engineered" by people trained by the NIS who sent large numbers of text messages to voters extolling the conservative candidate and current President Park Geun-hye, whilst spreading false information about her opponent.


수많은 권력남용의 사건 중에서, 시위자들은 당시 민주통합당의 후보였으며 가톨릭신자로서 이번 시국미사에 함께 참여한 문재인 의원이 패배했던 지난해의 대선을 언급했다. 문후보의 패배는 국정원에 의해 훈련된 사람들에 의해 "기획된" 것으로 보이는데, 이들은 다량의 문자를 유권자들에게 보내 보수당 후보이자 현 대통령인 박근혜를 칭송하고, 문재인 후보에 대한 잘못된 정보를 유포하였다.


The Catholic Priests' Association for Justice (CPAJ), set up under the Park dictatorship, took part in the prayer for the first time, and openly called for the dismantling of the NIS. After getting the go-ahead of the Korean bishops, who had previously spoken with Vatican officials, priests joined the long battle engaged by lay Catholics against the intelligence service, describing the situation as a "serious crisis".


독재자 박정희 대통령 집권시에 설립된 천주교정의구현전국사제단이 처음으로 미사에 참여했고, 공개적으로 국정원의 해체를 요구하였다. 바티칸 관계자들과 사전에 논의를 나눈 한국 주교들의 승인하에, 사제들은 현 상황을 "중대한 위기"라고 규정하며 가톨릭 평신도들이 오랫동안 참여해온 국정원 규탄 시위에 동참했다.


More than 5,000 ordinary citizens, men and women religious as well as lay people, took part in the demonstration, united in defending the right to personal liberty against a "dangerous organisation" that constitutes a " threat to democracy". Anonymous Catholic sources from Justice and Peace interviewed by the newspaper Hankyoreh said that the large presence of Catholics shows that, despite the bishops' great prudence, the situation is "dire".


5천명 이상의 가톨릭신도 혹은 비신도들이 "민주주의에 위협" 이 되고 있는 "위험한 기관"인 국정원에 맞서 개인의 자유에 대한 권리를 수호하기 위해 함께 연합하였다. 익명의 정의평화 위원회 소속 가톨릭 관계자는 한겨레 신문과의 인터뷰에서, 비록 주교들이 대단히 신중하게 행동하기는 하지만 가톨릭 교회의 대규모 시위참여는 상황이 "대단히 심각한" 것임을 보여준다고 말했다.


After the South Korean Church issued a protest manifesto against NIS interference, it was joined by civil society groups that have for weeks held vigils and protests in front of the headquarters of the NIS and of the ruling Conservative (Saenuri) Party. Everyone is calling for the resignation of top NIS officials, an apology from the government for the election fraud and the dismantling of the surveillance system that "brought the country back to the years of the military dictatorship" of the 1970s.


한국 가톨릭교회가 국정원 규탄 시위 성명서를 발표한 후, 몇 주 동안 국정원 본부와 보수 새누리당 당사 앞에서 촛불시위와 시위를 해 왔던 시민 단체들도 이에 합류하였다. 시위에 참여하는 모든 시민들은 국정원 최고 관리들의 사퇴와 선거부정에 대한 정부차원의 사과, 그리고 1970년대 "군부독재 시대로 나라를 되돌리고 있는" 감시체계의 해체를 요구하고 있다.


The National Intelligence Service (NIS) was created in 1961 as the Korea Central Intelligence Agency (KCIA). Its initial task was to supervise and coordinate domestic and international intelligence activities. However, thanks to its sweeping powers, it was able to intervene and actively influence South Korean politics. In 1981, it took the name of Agency for National Security Planning (ANSP), following a series of reforms instituted under President Chun Doo-hwan and the Fifth Republic. It assumed its current name in 1999.


국정원(NIS)은 한국 중앙 정보부(KCIA)로 1961년 처음 만들어졌다. 초기 임무는 국내와 해외의 정보 활동을 감시하고 조정하는 것이었다. 그러나, 막강한 권력을 소유함에 따라 국정원은 한국의 국내 정치에 개입하고 적극적인 영향력을 행사할 수 있게 되었다. 몇 차례의 개혁을 겪은 후, 국정원은 제5공화국의 전두환 대통령 집권시인 1981년 국가 안전 기획부 (ANSP)로 이름이 바뀌었다. 1999년부터 현재의 이름인 국정원을 사용하고 있다.



바티칸 라디오 기사바로가기 

http://en.radiovaticana.va/in2/articolo.asp?c=732037

반응형

[CookBook] Fragments 이해하기 -6-

2013. 9. 29. 22:47 | Posted by 솔웅


반응형

Fragment1Activity.java



public class Fragment1Activity extends Fragment {
    OnOptionSelectedListener  myListener;
    @Override
    public View onCreateView(LayoutInflater inflater,
        ViewGroup container, Bundle savedInstanceState) {
        Context c = getActivity().getApplicationContext();
        View vw = inflater.inflate(R.layout.fragment1, container, false);
        String[] products={"Camera", "Laptop", "Watch", "Smartphone", "Television"};
        ListView productsList = (ListView) vw.findViewById(R.id.products_list);
        ArrayAdapter<String> arrayAdpt= new ArrayAdapter <String>(c, R.layout.list_item, products);
        productsList.setAdapter(arrayAdpt);
        productsList.setOnItemClickListener(new OnItemClickListener(){
            @Override
            public void onItemClick(AdapterView<?> parent, View v, int position, long id){
                myListener.onOptionSelected(((TextView) v).getText().toString());  
            }
        });
        return vw;
    }
   
    public interface OnOptionSelectedListener {
        public void onOptionSelected(String message);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            myListener = (OnOptionSelectedListener) activity;
        } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement OnItemClickListener");
        }
    } 
}




이 Fragment1Activity 클래스는 Fragment 클래스를 extends 했습니다. onCreateView() 메소드 안에서는 LayoutInflater 객체가 fragment1.xml 에서 정의된 ListView를 inflate하기 위해 사용됐습니다. 이 리스트 뷰는 product_list라는 id를 가진 xml 내의 listview 를 가져와서 productsList 라는 객체에 넣었습니다. 그리고 ArrayAdapter 를 사용해서 list_item.xml 을 이용해서 각 아이템들을 세팅하고 구체적인 아이템 내용은 products 배열에서 가져오고 있습니다. 그리고 이 Adapter를 productsList에 세팅합니다. 그리고 productsList 에 onItemClickListener를 달아서 리스트뷰 내의 아이템이 선택되면 어떤 일을 하도록 정의합니다. setOnItemClickListener 안에는 inItemClick()이라는 콜백 메소드가 있는데요. 아이템이 클릭되면 이 메소드가 자동으로 호출됩니다. 여기서는 아이템이 클릭되면 onOptionSelected() interface를 호출하네요. 그 인터페이스 안에는 onOptionSelected() 메소드가 선언돼 있구요. 이 fragment와 연관된 activity는 OnOptionSelectedListener 인터페이스를 implements 했을 겁니다. 그리고 이 인터페이스의 body인 onOptionSelected() 메소드를 구현했을 거구요. 그러니까 여기서 아이템이 클릭되면 구체적인 동작은 이 OnOptionSelectedListener 인터페이스를 implements 한 activity에서 구현됩니다.



이제 만들어야 할 파일은 Fragment2Activity.java인데요. 여기서는 아래 두가지 일을 해야 합니다.

- fragment2.xml 에서 UI를 load 합니다.
- 유저가 선택한 제품을 출력할 dispOption 메소드를 정의 해야 합니다.



이 두가지 일을 하기 위해서 아래와 같이 코딩을 합니다.



Fragment2Activity.java



public class Fragment2Activity extends Fragment {
    TextView selectedOpt;
    String messageReceived="";

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View vw= inflater.inflate(R.layout.fragment2,  container, false);
           Bundle bundle=getArguments(); 
           if(bundle !=null) {
               messageReceived = bundle.getString("msg");
               selectedOpt = (TextView) vw.findViewById(R.id.selectedopt);
               selectedOpt.setText(messageReceived);
           }
           return vw;     
    }

    public void dispOption(String msg){
        TextView selectedOpt = (TextView) getActivity().findViewById(R.id.selectedopt);
        selectedOpt.setText("You have selected "+msg);  
    }
}


여기서도 fragment를 생성하기 위해 Fragment 클래스를 extends 했습니다. 그리고 onCreateView() 메소드를 오버라이드 해서 그 안에서 LayoutInflater 객체를 이용해 fragment2.xml 안에 정의된 TextView를 inflate 했습니다. 리스트뷰에서 선택된 제품 이름은 dispOption() 메소드로 전달되서 이 TextView 를 통해 화면에 뿌려질 겁니다.



이제 맨 처음 만든 activity_fragments_by_code_app.xml 을 불러와서 사용할 java 파일을 만들 차례입니다.
이 xml layout에 정의된 frag1_container와 frag2_container로 id가 정의된 LinearLayout 에 위에서 만든 fragment들을 배치시켜야겠죠.
소스 내용은 아래와 같습니다.



FragmentsByCodeAppActivity.java



public class FragmentsByCodeAppActivity extends Activity implements OnOptionSelectedListener {
    private static final String TAG1 = "1";
    private static final String TAG2 = "2";
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragments_by_code_app);
        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        if(null==fragmentManager.findFragmentByTag(TAG1)){
            Fragment1Activity fragment1 = new Fragment1Activity();
            fragmentTransaction.add(R.id.frag1_container, fragment1, TAG1); 
        }
        Bundle args = new Bundle();
        String message="Message from Fragment 1";  
        if(null==fragmentManager.findFragmentByTag(TAG2)){
            Fragment2Activity fragment2 = new Fragment2Activity();
            args.putString("msg", message);
            fragment2.setArguments(args);
            fragmentTransaction.add(R.id.frag2_container, fragment2, TAG2); 
        }
        fragmentTransaction.commit();
        }

    public void onOptionSelected(String msg){
        Fragment2Activity frag2 = (Fragment2Activity) getFragmentManager().findFragmentById(R.id.frag2_container);
        frag2.dispOption(msg);             
    }
}


보시면 FragmentManager 객체를 보실 수 있을 겁니다. fragment에 접근할 수 있도록 해주는 클래스 입니다. fragment를 추가하거나 제거하거나 replace를 해야 될 때 사용할 FragmentTransaction도 이 FragmentManager의 beginTransaction() 메소드를 사용해서 정의했습니다.



그리고 frag1_container에 첫번째 fragment를 넣고 frag2_container에 두번째 fragment를 넣었습니다. 넣기 전에 이미 존재하는지 여부를 먼저 체크했습니다. 이때 Fragmentmanager의 findFragmentByTag() 메소드를 사용했죠. 두번째 fragment에는 메세지도 argument로 세팅했습니다. 그 다음에 FragmentTransaction 클래스의 commit()메소드를 사용해서 작업을 완료합니다.



그 아래에 onOptionSelected() 메소드가 있는데요. 이것은 ListView에서 아이템이 선택됐을 때 실행될 메소드 입니다. 선택된 제품을 fragment2의 TextView에 표시하도록하는 메소드죠.



이로서 동적으로 fragment를 생성하고 할당해서 사용하는 코드가 완성됐습니다.

반응형