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

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형



So, we used to solve big problems. On July 21st, 1969, Buzz Aldrin climbed out of Apollo 11's lunar module and descended onto the Sea of Tranquility. Armstrong and Aldrin were alone, but their presence on the moon's gray surface was the culmination of a convulsive, collective effort.
   
우리들은 여러 big problems(큰 문제)들을 해결했습니다. 1969년 7월 21일, Buzz Aldrin 은 아폴로 11호 달 착륙선을 기어 나왔습니다. 그리고 고요의 바다에 내려왔죠. 거기에는 암스트롱과 Aldrin 뿐이었습니다. 하지만 달의 회색 지표위의 그들의 존재 자체가 그동안의 수많은 노력의 결정체였습니다.

The Apollo program was the greatest peacetime mobilization in the history of the United States. To get to the moon, NASA spent around 180 billion dollars in today's money, or four percent of the federal budget. Apollo employed around 400,000 people and demanded the collaboration of 20,000 companies, universities and government agencies. People died, including the crew of Apollo 1. But before the Apollo program ended, 24 men flew to the moon. Twelve walked on its surface, of whom Aldrin, following the death of Armstrong last year, is now the most senior.

아폴로 계획은 미국 역사상 가장 평화로운 시기에 있었던 일입니다. 달에 가기 위해 나사는 현재 가치로 천 8백억 달러를 사용했습니다. 이 액수는 연방 예산의 1/4 이나 됩니다. 아폴로는 40만명의 고용 효과를 냈었고 2만개 협력회사, 대학 그리고 정부 기관과 같이 진행을 했습니다.  아폴로 1호의 승무원을 비롯한 여러 사람들이 죽었습니다. 하지만 이 아폴로 계획이 끝나기 전까지 24명의 사람들이 달에 갔습니다. 그리고 그 중 12명이 달 표면을 걸었습니다. 작년에 암스트롱이 죽은 이후 Aldrin은 이제 살아남은 가장 고참자가 되었습니다.





So why did they go? They didn't bring much back: 841 pounds of old rocks, and something all 24 later emphasized -- a new sense of the smallness and the fragility of our common home. Why did they go? The cynical answer is they went because President Kennedy wanted to show the Soviets that his nation had the better rockets. But Kennedy's own words at Rice University in 1962 provide a better clue.?

그런데 왜 그들은 달로 갔을까요. 그들이 가져온 것은 그렇게 많지 않습니다. 841 파운드의 월석을 가져왔고 and something all 24 later emphasized -- a new sense of the smallness and the fragility of our common home. 왜 그들은 달로 갔을까요? 냉소적으로 답변한다면 그들이 달에 간 이유는 케네디 대통령이 소련에게 미국이 더 좋은 로케트를 가지고 있다는 것을 보여주기 위해서 입니다. 케네디가 1962년도에 Rice 대학교에서 한 연설에 좀 더 나은 실마리가 있을까요?

(Video) John F. Kennedy: But why, some say, the moon? Why choose this as our goal? And they may well ask, why climb the highest mountain? Why, 35 years ago, fly the Atlantic? Why does Rice play Texas? We choose to go to the moon. We choose to go to the moon. (Applause) We choose to go to the moon in this decade, and do the other things, not because they are easy, but because they are hard.

죤 F 케네디 : 그런데 왜, 달이었을 까요? 왜 이것을 우리의 goal 로 선택했을까요? 아마 사람들은 물을 겁니다. 왜 그 높은 산에 오르고 왜 35년 전에 대서양을 횡단하고 왜 Rice 는 텍사스에 있나요? 우리는 달에 가는 것을 선택했습니다. 우리는 달에 가는 것을 선택했습니다. 우리는 10년 이내에 달에 가는 것을 선택했고 그 일을 해 나갔습니다. 그것들이 쉬워서가 아닙니다. 그것들이 어렵기 때문입니다.




Jason Pontin: To contemporaries, Apollo wasn't only a victory of West over East in the Cold War. At the time, the strongest emotion was of wonder at the transcendent powers of technology. They went because it was a big thing to do. Landing on the moon occurred in the context of a long series of technological triumphs. The first half of the 20th century produced the assembly line and the airplane, penicillin and a vaccine for tuberculosis. In the middle years of the century, polio was eradicated and smallpox eliminated. Technology itself seemed to possess what Alvin Toffler in 1970 called "accelerative thrust." For most of human history, we could go no faster than a horse or a boat with a sail, but in 1969, the crew of Apollo 10 flew at 25,000 miles an hour.

제이슨 판틴 : 동시대에 아폴로만이 동서 냉전시대의 승리가 아니었습니다. 그 때에 크게 관심이 쏠렸던 부분은 기술력에서 누가 더 월등한가에 대한 것이었습니다. 달에 착륙함으로서 미국은 기술력의 우위를 확실하게 보여줄 수 있었습니다. 20세기 초반에 조립공정과 비행기, 페니실린 그리고 결핵에 대한 백신이 만들어 졌습니다. 20세기 중반에는
소아마비가 사라졌고 두창이 해결된 것이었습니다. 기술력은 1970년에 앨빈 토플러가 말했듯이 "accelerative thrust (가속적 추진력)" 을 가지고 있는 것처럼 보였습니다. 인류 역사상 우리는 말보다 빨리 달릴 수 없었고 보트 없이 항해를 할 수 없었습니다. 하지만 1969년도에 아폴로 10호의 승무원들은 시속 2만5천 마일로 날아갔습니다.

Since 1970, no human beings have been back to the moon. No one has traveled faster than the crew of Apollo 10, and blithe optimism about technology's powers has evaporated as big problems we had imagined technology would solve, such as going to Mars, creating clean energy, curing cancer, or feeding the world have come to seem intractably hard.

1970년 이래로 인류가 달에 다시 가지는 않았습니다. 그리고 아무도 아폴로 10호의 승무원보다 더 빠른 속도로 여행을 하지 않았습니다. 기술력에 대한 낙관주의가 사라졌습니다. 기술력이 큰 문제들 예를 들어 화성에 간다든지 clean energy를 만들어 낸다던지 암을 치료한다던지 혹은 전세계 식량문제 등을 해결할 것이라는 그런 행복한 낙관주의가 사라지고 이것들이 아주 힘든 문제로 보이기 시작했습니다.

I remember watching the liftoff of Apollo 17. I was five years old, and my mother told me not to stare at the fiery exhaust of a Saturn V rocket. I vaguely knew this was to be the last of the moon missions, but I was absolutely certain there would be Mars colonies in my lifetime.

아폴로 17호가 발사되는 장면이 기억납니다. 저는 5살이었습니다. 그리고 어머니가 Saturn V rocket 의 불꽃이 앞으로 더 이상 일어나지 않을 거라고 말했습니다. 저는 희미하게나마 이것이 달에서 하는 임무의 마지막이 될 거라는 것을 알게 되었습니다. 하지만 저는 제 생애에 분명 화성에 식민지를 건설할 것이라는 것을 확신 했었습니다.

So "Something happened to our capacity to solve big problems with technology" has become a commonplace. You hear it all the time. We've heard it over the last two days here at TED. It feels as if technologists have diverted us and enriched themselves with trivial toys, with things like iPhones and apps and social media, or algorithms that speed automated trading. There's nothing wrong with most of these things. They've expanded and enriched our lives. But they don't solve humanity's big problems.

그래서 "이제 기술력으로 우리가 당면한 큰 문제들을 해결할 역량이 되었다" 가 상식이 되었습니다. 아마 여러분도 이 얘기를 항상 들었을 겁니다. 우리는 지난 이틀동안 TED에서 이것과 관련해서 들었습니다. 아마도 기술자들은 우리의 이런 생각을 바꾸도록 하고 정작 그들은 사소한 장난감을 갖고 노는것 같은 느낌이 듭니다. 예를 들어 아이폰이나 앱들 그리고 Social Media 혹은 trading을 빠르게 자동화 시키는 알고리즘 같은 것들을요. 그런것들 연구한다고 뭐가 잘못된거는 아닙니다. 그것들이 우리의 삶을 확장시키고 풍부하게 만듭니다. 하지만 그런 것들이 인류의 큰 문제들을 해결하지는 않습니다.

What happened? So there is a parochial explanation in Silicon Valley, which admits that it has been funding less ambitious companies than it did in the years when it financed Intel, Microsoft, Apple and Genentech. Silicon Valley says the markets are to blame, in particular the incentives that venture capitalists offer to entrepreneurs. Silicon Valley says that venture investing shifted away from funding transformational ideas and towards funding incremental problems or even fake problems. But I don't think that explanation is good enough. It mostly explains what's wrong with Silicon Valley. Even when venture capitalists were at their most risk-happy, they preferred small investments, tiny investments that offered an exit within 10 years. V.C.s have always struggled to invest profitably in technologies such as energy whose capital requirements are huge and whose development is long and lengthy, and V.C.s have never, never funded the development of technologies meant to solve big problems that possess no immediate commercial value. No, the reasons we can't solve big problems are more complicated and more profound.

What happened? 여기 실리콘 밸리의 얘기가 있습니다. 인텔, 마이크로소프트, 애플 그리고 genetech 에 투자됐던 때에 투자된 다른 전망이 더 적었던 회사들이 있습니다. 실리콘밸리는 시장이 비난받아야 한다고 말합니다. 특히 벤처 투자가들이 사업가에 제안하는 그런 인센티브들입니다. 실리콘밸리는 벤처투자가들이 transformational ideas에 펀딩하려고 하지 않는다고 말합니다. 증가되는 문제들이나 심지어는 거짓 문제들에 투자를 한다고 합니다. 저는 이런 얘기들이 그렇게 충분히 좋은 얘기는 아니라고 봅니다. 이 이야기는 실리콘밸리에 무엇이 문제인가를 설명해 줍니다. 심지어 벤처투자가들이 가장 리스크가 적은 상황에 10년 이내에 결과를 도출할 수 있는 작은 규모의 투자를 선호합니다. 벤처투자자들은 항상 에너지 같이 큰 투자가 요구되고 오랜기간 동안 개발되어야 할 technology 에 투자를 할 때 고민스러워 합니다. 벤처투자가들은 즉각적인 상업적 가치가 없는 그런 큰 문제들을 풀기 위한 technology들을 위한 개발에는 절대 펀딩을 하지 않습니다. 우리가 이런 큰 문제들을 해결할 수 없는데에는 그 외에도 좀 더 복잡하고 좀 더 심오한 장애물들이 있습니다.

Sometimes we choose not to solve big problems. We could go to Mars if we want. NASA even has the outline of a plan. But going to Mars would follow a political decision with popular appeal, and that will never happen. We won't go to Mars, because everyone thinks there are more important things to do here on Earth.

가끔 우리들은 큰 문제들을 해결하지 않는 쪽을 선택합니다. 우리가 원하면 우리는 화성에 갈 수 있습니다. 나사는 우주선에 대한 outline도 가지고 있습니다. 하지만 화성에 가는것은 대중적인 요구와 정치적인 결단이 필요합니다. 그리고 그런 상황은 절대 일어나지 않습니다. 우리는 화성에 가지 않을 겁니다. 왜냐하면 모두들 이 지구에 그것보다 더 중요한 것들이 있다고 생각하기 때문입니다.

Sometimes, we can't solve big problems because our political systems fail. Today, less than two percent of the world's energy consumption derives from advanced, renewable sources such as solar, wind and biofuels, less than two percent, and the reason is purely economic. Coal and natural gas are cheaper than solar and wind, and petroleum is cheaper than biofuels. We want alternative energy sources that can compete on price. None exist. Now, technologists, business leaders and economists all basically agree on what national policies and international treaties would spur the development of alternative energy: mostly, a significant increase in energy research and development, and some kind of price on carbon. But there's no hope in the present political climate that we will see U.S. energy policy or international treaties that reflect that consensus.

어떤 경우에는 political system 이 실패를 했기 때문에 이런 큰 문제들을 해결하지 못하기도 합니다. 오늘날 태양열이나 풍력 그리고 바이오 연료 같이 진보적이고 새로운 원료로부터 얻어진 에너지를 소비하는 비율은 전세계적으로 2% 미만 입니다. 2% 미만이요. 그 이유는 바로 경제적인 이유 때문입니다. 석탄과 천연가스들은 태양력이나 풍력보다 쌉니다. 그리고 석유는 바이오연료보다 쌉니다. 우리는 가격 경쟁력 있는 대안 에너지가 필요합니다. 하지만 그런것은 존재하지 않습니다. 이제 기술자들과 경제지도자들은 기본적으로 이런 대안에너지를 전세계적차원에서 또는 전 국가적 차원에서 본격적으로 개발해야 한다는데 동의하고 있습니다. 하지만 현재의 정치적인 상황하에서는 별 희망이 없어 보입니다.

Sometimes, big problems that had seemed technological turn out not to be so. Famines were long understood to be caused by failures in food supply. But 30 years of research have taught us that famines are political crises that catastrophically affect food distribution. Technology can improve things like crop yields or systems for storing and transporting food, but there will be famines so long as there are bad governments.

어떤 경우에는 큰 문제들이 기술적으로 그렇게 되지 않아야 되는 경우가 있습니다. 음식 공급이 실패함으로서 초래된 기아에 대해 모두 알고 있습니다. 30년 동안의 연구 결과가 말해주듯이 기아는 정치적인 위기가 음식 공급체계를 파멸시켜 일어납니다. 기술이 작물 수확이나 음식을 저장하고 운송하는 부분을 개선시킬 수 있습니다. 하지만 기아는 대개 나쁜 정부에서 기인합니다.

Finally, big problems sometimes elude solution because we don't really understand the problem. President Nixon declared war on cancer in 1971, but we soon discovered there are many kinds of cancer, most of them fiendishly resistant to therapy, and it is only in the last 10 years that effective, viable therapies have come to seem real. Hard problems are hard.

마지막으로 큰 문제들은 가끔 그 해결책들을 피해갑니다. 왜냐하면 우리가 진짜 그 문제가 무엇인지 이해를 못하기 때문이죠. 닉슨 대통령은 1971년 암과의 전쟁을 선포했습니다. 하지만 우리는 곧 암에는 아주 많은 종류가 있다는 것을 발견했죠. 그리고 그 대부분은 치료가 무척 어렵습니다. 효과적이고 유용한 치료법들이 현실화 되기 시작한 건 오직 10년 정도 전 부터 입니다. 어려운 문제들은 해결이 어렵습니다.



It's not true that we can't solve big problems through technology. We can, we must, but these four elements must all be present: Political leaders and the public must care to solve a problem; institutions must support its solution; It must really be a technological problem; and we must understand it.

기술을 통해서 큰 문제들을 해결할 수 없다는 것은 맞지 않습니다. 우리는 할 수 있습니다. 그리고 반드시 해야 합니다. 하지만 이 4가지 문제가 존재합니다. 정치 지도자와 대중들은 반드시 문제를 해결하려고 해야 합니다. 연구소들은 반드시 그 해결방법을 지원해야 합니다. 그리고 그것들은 기술적인 문제여야 하고 우리들은 그것을 이해하고 있어야 합니다.

The Apollo mission, which has become a kind of metaphor for technology's capacity to solve big problems, met these criteria. But it is an irreproducible model for the future. It is not 1961. There is no galvanizing contest like the Cold War, no politician like John Kennedy who can heroize the difficult and the dangerous, and no popular science fictional mythology such as exploring the solar system. Most of all, going to the moon turned out to be easy. It was just three days away. And arguably it wasn't even solving much of a problem.

아폴로의 성과는 큰 문제들을 해결하기 위해 기술력의 capacity가 얼마나 되느냐에 대한 일종의 metaphor 가 됐습니다. 하지만 이것은 미래에 재생할 수 없는 모델입니다. 지금이 1961년도가 아닙니다. 냉전같은 그런 외적요건이 더이상 없습니다. 그리고 케네디같이 영웅적으로 태양계를 항해하는 것 같은 대중적이지 않은 과학적 신화같은 어렵고 위험한 문제를 하결하고자 하는 정치인이 없습니다. 무엇보다도 달에 가는 것은 이제 아주 쉬운 일이 되어 버렸습니다. 그냥 3일만에 다녀올 수 있습니다. 그리고 그것은 어떤 문제들을 해결하지도 못합니다.

We are left alone with our day, and the solutions of the future will be harder won. God knows, we don't lack for the challenges.
우리는 우리 시대에 남겨져 있습니다. 그리고 미래의 해결책은 좀 더 어려울 것입니다. 신만이 아실 겁니다. 도전을 멈추지 말아야 할 겁니다.

Thank you very much.
감사합니다.

(Applause)

반응형

[CookBook] Fragments 이해하기 -10-

2013. 10. 2. 12:08 | Posted by 솔웅


반응형

Setting user's Preferences with PreferenceFragment


PreferenceFragment는 유저가 어플리케이션을 configure하고 personalize할 수 있도록 하는 fragment 입니다. 이 PreferenceFragment는 여러개의 preference view들을 가질 수 있습니다. 애플리케이션의 preference를 쉽게 세팅할 수 있도록 도와주기 위해서이죠. PreferenceFragments에는 아래와 같은 preference view 들이 있습니다.



PreferenceScreen : preference screen을 정의하기 위해 사용되는 XML의 root element.

CheckBoxPreference : check되면 true를 안되면 false를 return 하는 간단한 check box를 표시한다.

ListPreference : 사용자가 선택할 수 있는 radio button들의 리스트를 표시한다.

EditTextPreference : 사용자가 텍스트를 입력할 수 있는 EditText dialog를 표시한다.

RingtonePreference : ringtone을 가리키는 radio button을 표시한다.

PreferenceCategory : 카테고리 내의 관계된 preference들을 grouping 한다.

Preference : Button 처럼 사용하는 custom preference



어떻게 어플리케이션 preference들이 세팅되는지 이해하기 위해 PrefFragmentApp이라는 안드로이드 프로젝트를 일단 만들어 보죠. pPreferenceFragment에서 preference view들을 표시하는 방법에는 두가지가 있습니다. XML 파일을 이용하는 방법과 code를 이용하는 방법이 있습니다. 우리는 XML을 이용하는 방법을 시도해 보겠습니다. 그러니까 먼저 res 폴더 밑에 xml 이라는 폴더를 먼저 만드셔야 합니다. 이 res/xml 이라는 폴더 밑에 preference.xml 이라는 XML 파일을 추가하시면 됩니다. 이 xml 에는 어플리케이션의 configure를 위해 유저에게 표시될 preference view들이 선언돼 있습니다. 이 preference view들 중 유저가 선택한 옵션들은 어플리케이션 내에 계속 유지될 겁니다.






preference.xml



<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
    <PreferenceCategory android:title="Category 1">
        <CheckBoxPreference
            android:title="Newsletter"
            android:defaultValue="false"
            android:key="Newskey"  />
        <EditTextPreference android:key="Namekey"
            android:title="Enter your name: "
            android:dialogTitle="Enter your name" >
        </EditTextPreference>
    </PreferenceCategory>
    <PreferenceCategory android:title="Category 2">
        <RingtonePreference android:showDefault="true"
            android:key="Audio" android:title="Select sound"
            android:ringtoneType="notification" >
        </RingtonePreference>
        <ListPreference android:title="Products List "
            android:key="products_list"
            android:entries="@array/products"
            android:entryValues="@array/prodselected"
            android:dialogTitle="Choose a product" >
        </ListPreference>
    </PreferenceCategory>
    <Preference
        android:title="Submit"
        android:key="submitPref" />
</PreferenceScreen>



이 PreferenceScreen 안에는 두개의 PreferenceCategory가 있는게 보이실 겁니다. Category 1에는 CheckboxPreference, EditTextPreference 이렇게 두개의 preference view가 있습니다. Category 2에는 RingtonePreference, ListPreference 이렇게 있구요. 모든 preference view는 android:key 값을 가져야 합니다. 일정의 id이죠. android:title 속성은 preference view의 초기값을 할당하기 위해 사용됩니다. 그리고 android:defaultValue 속성은 preference view에 디폴트 값을 할당할 때 사용되구요.



CheckBoxPreference는 UI element로서 check box를 표시합니다. 여기에는 Boolean 형식으로 값이 저장되구요. 체크박스가 선택되면 true값이 선택되지 않으면 false 값이 저장됩니다.  android:default 속성을 사용해서 디폴트 값을 false로 설정했습니다.



EditTextPreference 는 android:key 속성에 Namekey 라고 정해져 있습니다. 그리고 android:title에는 Enter your name : 이 지정돼 있구요. 이 EditTextPreference 가 선택되면 title이 Enter your name 이라는 dialog가 뜰 겁니다. 사용자가 정보를 입력하고 OK 버튼을 클릭하면 입력된 정보가 preference store에 저장됩니다.



RingtonePreference는 ringtone 리스트가 있는 dialog box를 보여줄 겁니다. 그리고 사용자가 default ringtone이나 silent mode를 선택할 수 있도록 합니다. 여기에 android:key 속성에는 Audio라고 설정이 돼 있습니다. 그리고 title은 Select sound라고 돼 있죠. android:ringtoneType은 display 될 ringtone 리스트를 정합니다. 여기에 들어갈 수 있는 값은 ringtone, notification, alarm 그리고 all 이 들어갈 수 있습니다.



ListPreference 에는 radio 버튼 형식으로 preference들의 세트를 dialog box 에 보여 줍니다. 사용자가 그 중 하나를 선택할 수 있는 거죠. 이 dialog box의 title은 Choose a product 가 될 겁니다. android:key 속성에는 product_list가 대입 됐구요. android:endtries 속성은 preference들의 리스트를 보여주기 위해 ListPreference에 product라는 이름의 배열이 할당됐습니다. 이 배열에 있는 값들이 ListPreference를 통해서 표시되는 radio button들의 아이템이 될 겁니다. android:entryValues 속성은 prodselected라고 하는 다른 배열을 정의하는데요. product 배열에 정의된 요소들의 값을 잡아두고 있기 위해서 세팅됐습니다. android:entryValues 속성은 사용자가 선택한 radio button에 해당되는 값들을 저장하는 배열입니다.



<Preference> element는 PreferenceFragment에 Submit Button을 표시합니다. 이 Submit button은 여기서 android:key 속성에 해당되는 값이 submitPref로 돼 있습니다. 자바코드에서 이 값을 갖고 콘트롤 할 겁니다.



이제 strings.xml에 두개의 배열을 정의할 겁니다. 하나는 ListPreference의 radio button에 표시될 텍스트들이구요 다른 하나는 첫번째 배열과 대응하는 값들 입니다. 이 xml은 res/values 폴더 안에 있게 됩니다.



strings.xml



<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">PrefFragmentApp</string>
    <string name="menu_settings">Settings</string>
    <string-array name="products">
        <item>Camera</item>
        <item>Laptop</item>
        <item>Watch</item>
        <item>Smartphone</item>
        <item>Television</item>
    </string-array>
    <string-array name="prodselected">
        <item>You have selected Camera</item>
        <item>You have selected Laptop</item>
        <item>You have selected Watch</item>
        <item>You have selected Smartphone</item>
        <item>You have selected Television</item>  
    </string-array>
</resources>


products 배열에 있는 element들은 ListPreference에 보이는 radio buttons 옆에 표시될 텍스트 들입니다. prodselected 배열은 위 products 배열중에서 선택된 것들에 대한 return 값들이 들어 있습니다.



preference.xml에 있는 이 preference view들을 load 하기 위한 자바클래스가 필요 합니다. 아래 그 샘플 코드가 있습니다.



PrefFragActivity.java



public class PrefFragActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getFragmentManager().beginTransaction().replace(android.R.id.content, new PrefsFragment()).commit();
    }

    public static class PrefsFragment extends PreferenceFragment  {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.preferences);
            Preference submitPref = (Preference) findPreference("submitPref");
            submitPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
                public boolean onPreferenceClick(Preference preference) {
                    getActivity().finish();
                    return true;
                }
            });
        }
    }
}



PreferenceFragment를 사용하기 위해 자바 클래스에서 PreferenceFragment를 extends 합니다. addPreferencesFromResource() 메소드는 XML 파일(preferences.xml)에 있는 PreferenceFragment에 있는 preference view를 load하기 위해 호출됩니다. preferences.xml에서 <Preference) element를 사용해 정의된 Submit 버튼은 submitPref라는 Preference 객체를 통해서 접근되고 매핑이 됩니다. 이것의 콜백 메소드인 onPreferenceClick()은 submitPref 객체가 클릭됐을 떄 실행됩니다. 이 onPreferenceClick() 메소드는 이 activity를 finish() 하고 선택된 preferences에 필요한 action을 하기 위해 PreferenceFragActivity.java로 돌아 갑니다. 이 PrefFragmentAppActivity자바 activity 파일을 통해 텍스트뷰에 유저가 선택한 preference를 표시할 겁니다.



이 PreferenceFragment에 보여지는 preference view들로부터 선택된 옵션을 표시하기 위해 4개의 텍스트뷰가 정의되어야 합니다. 아래 그 layout xml 파일이 있습니다.



activity_pref_fragment_app.xml



<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/newsletter"
        android:textSize="@dimen/text_size"        
        android:textStyle="bold" />
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/name"
        android:textSize="@dimen/text_size"
        android:textStyle="bold" />
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/ringtone"
        android:textSize="@dimen/text_size"
        android:textStyle="bold" />
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/product"
        android:textSize="@dimen/text_size"
        android:textStyle="bold" />
</LinearLayout>



위 layout xml 파일을 보면 4개의 텍스트뷰가 있고 각각 id 는 각각 newsletter, name, ringtone, product 입니다. 이 텍스트뷰는 LinearLayout 안에서 아래 위로 배치됩니다. newsletter 텍스트뷰에는 CheckBoxPreference의 체크박스에 유저가 체크했는지 여부가 표시될 겁니다. name 텍스트뷰는 EditTextPreference에 유저가 입력한 이름이 표시될것이고 ringtone 텍스트뷰는 유저가 선택한 RingtonePreference의 ringtone이 표시될 겁니다. product 텍스트뷰에는 ListPreference에서 유저가 선택한 product가 표시됩니다.



PreferenceFragment를 표시하고 사용자가 선택한 preference들을 보여주기위해 아래와 같은 자바파일을 만듭니다.



PrefFragmentAppActivity.java



public class PrefFragmentAppActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pref_fragment_app);
        startActivity(new Intent(this, PrefFragActivity.class));
    }

    @Override
    public void onResume() {
        super.onResume();
        SharedPreferences prefs=PreferenceManager.getDefaultSharedPreferences(this);
        TextView newsletter=(TextView)findViewById(R.id.newsletter);
        TextView name=(TextView)findViewById(R.id.name);
        TextView ringtone=(TextView)findViewById(R.id.ringtone);
        TextView product=(TextView)findViewById(R.id.product);
        if(Boolean.valueOf(prefs.getBoolean("Newskey", false)))
            newsletter.setText("You have selected Newsletter");
        else
            newsletter.setText("");
        ringtone.setText("The ringtone selected is "+prefs.getString("Audio", "Silent"));
        name.setText("The name entered is "+prefs.getString("Namekey",""));
        String selectedProduct = prefs.getString("products_list", "Camera");
        product.setText(selectedProduct);
    }
}



이 PreferenceFragment를 표시하기 위해 PrefFragActivity 클래스가 시작됩니다. PreferenceFragment에서 사용자가 선택한 preferences를 보여주기 위해 activity_pref_fragment_app.xml 인 layout 파일에 텍스트 뷰들이 정의돼 있습니다. 이 preference 뷰들에서 선택된 옵션을 찾기 위해  prefs로 명명된 SharedPreferences 객체를 생성했습니다. getInt(), getString(), getBoolean() 메소드를 통해 이 SharedPreferences 객체로부터 그 값들을 수집합니다.



CheckBoxPreference의 값을 읽기 위해서는 getBoolean() 메소드를 사용하고 CheckBoxPreference의 key를 전달해서 값을 받습니다. 이 Newskey라는 key가 SharedPreference 인스턴스의 getBoolean()메소드를 통해 전달 됐을 때 이 CheckBoxPreference는 true나 false 를 return 할 겁니다.


그리고 EditTextPreference는 SharedPreference 인스턴스의 getString()메소드로 Namekey라는 key를 전달합니다. 디폴트는 empty string 입니다. RingtonePreference와 ListPreference도 Audio와 product_list라는 key 값을 SharedPreference인스턴스의 getString() 메소드를 통해서 전달합니다. preference view들에서 사용자에 의해 선택된 preference들은 택스트뷰들을 통해 표시됩니다. ringtone의 디폴트값은 Silent 이고 product는 Camera 입니다.



이 PrefFragActivity.java 를 안드로이드에 보이도록 하려면 아래 코드를 AndroidManifest.xml에 추가하셔야 합니다.



<activity android:name=".PrefFragActivity" android:label="@string/app_name" />



Summary
 
 이 챕터에서는 fragments의 사용법과 다른 화면 크기에 맞게 어플리케이션을 적용하는 방법에 대해 다뤘습니다. fragment life cycle과 runtime시 동적으로 이 fragment를 추가하는 방법도 다뤘습니다. 그리고 fragment들 사이에 데이터를 전달하고 받는 방법도 배웠습니다. 그리고 ListFragment, DialogFragment 그리고 PreferenceFragment에 대해서도 배웠습니다.


반응형

[CookBook] Fragments 이해하기 -9-

2013. 10. 1. 21:11 | Posted by 솔웅


반응형

Displaying Dialog Through DialogFragment



안드로이드에서는 dialogs가 비동기적입니다. 동기적인 dialogs들은 이 dialog가 실행되는 동안 activity가 suspends 됩니다. 유저가 이 dialog를 사용하고 있는 동안에는 다른 것들이 올 수 없습니다. 비동기적인 dialogs들은 유저가 dialog를 사용하고 있는 동안에도 activity의 작업은 계속 됩니다. 이 activity는 콜백 메소드를 implement 함으로서 dialog와 함께 유저의 접근을 허용할 수 있습니다. 안드로이드의 dialogs는 자연스럽습니다. dialog가 open 돼 있는 동안 유저는 어플리케이션의 다른 부분에 접근할 수 없습니다. dialog를 비동기적으로 호출하는 방법의 잇점은 코딩을 줄일 뿐만 아니라 code를 통해서 이 dialog를 dismiss 할 수 있는 기능이 제공 된다는 것입니다.



DialogFragment base class를 extends 함으로서 DialogFragment를 사용하실 수 있습니다. 이 DialogFragment base 클래스는 Fragment 클래스에서 파생된 것입니다. 이 DialogFragment를 구현하기 위해 DialogFragmentApp이라는 프로젝트를 만들겠습니다. 여기에는 두개의 fragments들이 있을 건데요. 하나는 DialogFragment를 보여줄거고 다른 하나는 텍스트뷰를 보여줄 겁니다. DialogFragment와 유저의 상호작용은 두번째 fragment에 있는 텍스트뷰를 통해서 이뤄질 겁니다. DialogFragment에 있는 selected button은 두번째 fragment의 텍스트뷰를 통해서 display 됩니다.




이 DialogFragment를 만들기 전에 우선 텍스트뷰를 가지고 있는 fragment의 UI를 정의하겠습니다.


fragment2.xml



<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView 
        android:id="@+id/selectedopt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Select Open Dialog Button"
        android:textSize="@dimen/text_size"
        android:textStyle="bold" />
</LinearLayout>



LinearLayout 안에 id 가 selectedopt인 한개의 TextView 가 있습니다. 여기에 할당된 텍스트는 Select Open Dialog Button이네요. 볼드체이고 사이즈는 dimension resource의 text_size를 갖다가 사용합니다.
이 UI를 load 할 자바 클래스를 만들어 보죠.



Fragment2Activity.java



public class Fragment2Activity extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment2, container, false);
    }
}



아주 간단합니다. Fragment base 클래스를 extends 했고 onCreateView() 메소드 안에는 방금 만들었던 fragment2.xml 의 UI를 로드하기 위해 LayoutInflater를 사용했습니다.



이 fragment를 사용할 layout xml파일을 만들겠습니다.



activity_dialog_fragment_app.xml



<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >
    <fragment
        android:name="com.androidtablet.dialogfragmentapp.Fragment2Activity"
        android:id="@+id/fragment2"
        android:layout_weight="0"
        android:layout_width="wrap_content"
        android:layout_height="match_parent" />
    <Button
        android:id="@+id/dialog_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Open Dialog"
        android:textSize="@dimen/text_size" />
</LinearLayout>


Button 이 있습니다. 이 버튼을 클릭하면 DialogFragment가 나타나도록 할 겁니다. fragment와 button 이 LinearLayout 안에 배치해 있습니다. Fragment는 id 가 fragment2 이고 Button 은 id 가 dialog_button 입니다. Caption은 Open Dialog로 돼 있네요. 이 Caption은 dimention resource에서 text_size로 정의된 텍스트 크기를 가질 거구요.



이제 DialogFragment를 보여줄 코드를 작성할 차례입니다. DialogFragment를 보이기 위해서 자바 클래스는 DialogFragment 클래스를 extend 해야 합니다.



Fragment1Avtivity.java



public class Fragment1Activity extends DialogFragment{
    static Fragment1Activity newInstance(String title) {
        Fragment1Activity fragment = new Fragment1Activity();
        Bundle args = new Bundle();
        args.putString("title", title);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {   
        String title = getArguments().getString("title");
        Dialog diag = new AlertDialog.Builder(getActivity())
        .setIcon(R.drawable.ic_launcher)
        .setTitle(title)
        .setPositiveButton("OK", new DialogInterface.
            OnClickListener() {
            public void onClick(DialogInterface dialog, int
                whichButton) {
                ((DialogFragmentAppActivity) getActivity()).PositiveButton();
            }
        })
        .setNegativeButton("Cancel", new DialogInterface.
            OnClickListener() {
            public void onClick(DialogInterface dialog, int
                whichButton) {
                ((DialogFragmentAppActivity) getActivity()).NegativeButton();
            }
        }).create();
 
        return diag;
    }
}



보시다시피 DialogFragment를 생성하기 위해 이 자바 클래스는 DialogFragment 클래스를 extends 했습니다.
newInstance() 메소드는 이 fragment의 new instance를 생성합니다. 이 DialogFragment의 제목이 파라미터로 전달 됩니다. 이 파라미터는 Bundle 에 저장되고 fragment에 세팅 됩니다. (setArguments().



DialogFragment의 view hierarchy를 생성하기 위해 onCreateDialog() 메소드를 오버라이드 합니다. 그리고 title을 만들기 위한 Bundle 객체가 파라미터로 전달 됩니다. 이 onCreateDialog() 메소드 안에서 이 Dialog를 생성하기 위해 AlertDialog.Builder()를 사용하시는 것을 보실 수 있을 겁니다. 여기에 아이콘을 세팅하고 타이틀을 세팅하고 OK 버튼과 Cancel 버튼을 생성합니다.
이 OK와 Cancel 버튼에는 각각 onClickListener()를 달구요. OK를 클릭하면 PositiviButton() 메소드가 호출 디고 Cancel 버튼을 클릭하면 NegativeButton()이 호출 됩니다.



마지막에 이 메소드에서는 이 AlertDialog를 return 하구요.



이제 이 DialogFragment를 invoke 시킬 자바 액티비티 파일을 만들어야 합니다. 이 java activity file에는 OK와 Cancel을 눌렀을 때 실행되어야 할 PositiveButton()과 NegativeButton()메소드들이 구현되어야 하구요.



DialogFragmentAppActivity.java



public class DialogFragmentAppActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dialog_fragment_app);
        Button dialogButton = (Button)findViewById(R.id.dialog_button);
        dialogButton.setOnClickListener(new Button.OnClickListener(){
            @Override
            public void onClick(View arg0) {
                Fragment1Activity dialogFragment =
                    Fragment1Activity.newInstance( "Continue Processing?");
                dialogFragment.show(getFragmentManager(),  "Dialog Fragment Example");
            }
        });
    }

    public void PositiveButton() {
        TextView selectedOpt = (TextView)findViewById(R.id.selectedopt);
        selectedOpt.setText("You have selected OK button");
    }

    public void NegativeButton() {
        TextView selectedOpt = (TextView) findViewById(R.id.selectedopt);
        selectedOpt.setText("You have selected Cancel button");   
    }
}


onCreate() 메소드를 보시면 아까 만들었던 activity_dialog_fragment_app.xml 의 UI를 view로 set 하고 그 안의 Button에 대한 객체를 만듭니다. 그리고 이 버튼에 리스너를 달아서 클릭하면 Fragment1Activity.java 의 newInstance() 메소드를 호출합니다. 이때 타이틀이 될 Continue Processing?이라는 텍스트가 파라미터로 전달 되구요.
이 DialogFragment는 show() 메소드를 호출함으로서 visible 하게 됩니다. 이 show() 메소드는 이 fragment를 주어진 FragmentManager에 추가하게 되죠.
이 코드에는 아까 말했듯이 PositiveButton()과 NegativeButton() 메소드가 구현되었습니다. OK와 Cancel 버튼이 눌렸을 때 호출될 메소드 들입니다. 이 두 메소드에서는 모두 selectedopt라는 id를 가진 텍스트뷰의 객체를 만들고 여기에 text를 세팅하고 있습니다.



이 앱을 실행하고 Open Dialog 라는 버튼을 누르면 AlertDialog가 뜹니다. 여기서 OK를 누르면 이 Dialog 가 사라지고 왼쪽의 텍스트뷰에 You have selected OK Button이 쓰여지고 Cancel을 누르면 You have selected Cancel button 이 출력됩니다.



이 Dialog box는 사용자에게 중요한 메세지를 alert 하거나 사용자로부터 어떤 feedback을 받을 때 사용합니다.

반응형