마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

스피너가 onCreate에 무조건 selection 이벤트가 발생하면서...

0 추천
Spinner를 만들다보면, 사용자가 spinner drop down으로 설정한 값을 저장했다가  다시 어플을 실행하면 그 설정한 값으로 selection을 설정하려는 시도를 하게되는데요..

이럴때 Spinner.setSelection(int index)를 씁니다. 문제는 사용자가 spinner 하위 dropdown에서 하나 설정할때 특정 동작을 하게 한 경우, 어플이 실행되면서 onCreate에서 무조건 spinner가 setSelection이 동작해서 특정동작을 강제 실행한다는 점입니다. 그러니까 사용자가 터치해서 선택하는 경우에만 어떤 동작을 하게 하려고 구현한건데...어플이 실행되면 강제로 실행된다는 아이러니한...상황이 발생하는거죠...

Spinner의 고질적인 문제인거 같은데요. Spinner에서 선택한 값으로 저장하고 실행될때 Spinner를 그 값으로 설정할때 어떻게 하시는지요..저처럼 setSelection을 쓰시나요? 그렇게 되면 사용자가 터치해서 spinner index를 바꾸는경우와 어떻게 구별하나요...이런 경우 굉장히 많을 듯 싶은데요..^^
키웰 (210 포인트) 님이 2014년 2월 12일 질문

4개의 답변

0 추천
 
채택된 답변
한참을 헤메다가 찾아냈습니다. 일단 Spinner로 분명 저같이 고생하시는 분이 계실줄로 생각됩니다.

저의 이슈는 아래와 같습니다.

1. Spinner는 onCreate시 자동으로 onItemSelected가 실행된다.

2. Spinner의 index를 저장했다가 다시 불러오는 경우 setSelection을 사용한다.

3. setSelection을 사용하게되면 onItemSelected가 실행되버린다.

 

그러니까 사용자가 click하는 경우에만 spinner가 동작하도록 만들고 싶은 분은 굉장히 어려운 상황에 봉착할수 있는거죠.

방법은 system time을 check하는 겁니다.

System.currentTimeMillis() 을 onCreate와 onResume에 실행시켜서 저장시켜놓았다가 onItemSelected에서 다시 current time을 읽어서 저장해놓은 값과 비교하는 거죠.그 차이가  대략 200 미리이하면 onCreate에서 실행되었다는 의미가 됩니다. 사용자가 아무리 빨라도 200m 안에 누를수는 없죠.

 

저같이 고생하시는 분들은 참고하세요 ^^
키웰 (210 포인트) 님이 2014년 2월 12일 답변
checkbox의 경우 checkedChanged 이벤트의 checkboxview.isPressed()
메서드로 사용자의 입력인지 판단 가능합니다...
아마 spinner도 가능할듯하네요...
@Override
            public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
if(arg1.isPressed()){
//사용자 입력. 여기서만 처리
}
            }

이런식으로요...
지금 확인해봤는데요. spinner에서는 view값이 아무것도 들어오지 않네요. 아무래도 spinner에서는 사용하기 어렵겠어요..checkbox라면 가능할수도..
아니면 초기화 플래그 하나 두시고...
작업이랑 셋팅할 것 다 하시고
setSelection(~~~~~)
initialized = true;
하시는 것도...

public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
if(initialized){
//사용자 입력. 여기서만 처리
}
써주신 글 참고해서 나름 처리했습니다 도움이되었어요
같은 방식인데 시간이 아니라 선택값으로 처리했어요


전제 // 스피너의 현재 선택값을 어댑터 전역변수에 저장하고 있다(sortType)
 
스피너객체.setOnItemSelectedListener(new
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
int cur = sortType; //  현재 저장된 값을 잠시 가지고 있는다
 
// 선택 아이템에 따른 동작 구현에는 전역변수의 값을 바꾸는 동작이 포함되어있다
if(i == SORT_OPTION_ABC){
sortType = SORT_OPTION_ABC;
}else if(i == SORT_OPTION_TYPE){
sortType = SORT_OPTION_TYPE;
}
// 잠시 저장된 값이 전역변수에 저장된 값과 다르면
if(cur!=sortType){
 갱신 ㄱㄱ
}
지금 하고 계신 일이 프로그래밍 관련쪽이시면
빠른 시일 내에 다른 직종으로 전업하시길 권장합니다.
프로그래밍에서 가장중요한 요소 중 하나 프로그램의 신뢰성입니다.
만약 사용자가 200m보다 빠르게 클릭한다면요?
이 소스를 포함하고 있는 어플리케이션을 과연 신뢰성이 있는 어플리케이션이라고 말할 수 있을까요??
프로그래밍이라는 것은 철저히 객관적인 근거에 의해 소스를 생성해야합니다.
주관적인 생각으로 소스코드의 신뢰성을 떨어뜨리는 행동은 삼가하시길바랍니다.
게다가 이런 명백히 잘 못된 소스를 답변으로 올리는 것은 좋지 않은 행동이라고 생각합니다.

그나마 좀 더 나은 대안책으로는 사용자가 스피너를 직접 클릭했을때 발생하는 클릭이벤트와 클릭유무 판별 플래그를 선언해 onItemSelected 내부에서 사용자가 직접 클릭해서 선택된 경우와 그렇지 않고 내부 소스를 통해 선택된 경우를 판단하는 방법이 옳다고 생각합니다.
잘못되면 고칠점을 말해주면 될것을 직종을 바꾸라느니 좀 심하신듯;; 피해망상있으심?
뭔데 전업을 하래 웃기는 사람이네
 당신은 인생이나 되돌아 보셈
+1 추천
음... onCreate() 에서 setSelection() 을 처리하기 전에 setOnItemSelectListener() 를 앞서 정의하였기 때문에 그런 일이 발생합니다.

onItemSelected 이벤트가 필요하지 않는 순간에는 아래처럼 리스너를 제거하였다가 필요시 다시 달아주면 이벤트가 발생하지 않습니다.

1. spinner.setOnItemSelectedListener(null);

2. spinner.setSelection(position);

3. spinner.setOnItemSelectedListener(사용하던 리스너 객체);

요런식으로 리스너를 띠어내고 처리후 다시 붙이는 방식으로 했었는데 원하는 답변인지 모르겠네요..
dante2k (8,390 포인트) 님이 2014년 2월 12일 답변
이렇게 해도 의도한 대로 동작하지 않습니다.
제가 테스트해본바로는 setSelection을 호출했을 때 리스너의 메소드가 호출되는게 아니었습니다. 내부적으로 callback 객체를 post 해서 실제 리스너는 나중에 호출됩니다.
인터프리터 언어로 개발 하시다가 안드로이드로 넘어 오신 분 같은데
공부를 상당히 더 하셔야 할것같습니다.
그리고 잘못된 정보를 테스트없이 다른 사람에게 전파하는 행동은 상당히 좋지않은 행동입니다.
윗분이 답변하셨지만 안드로이드에서 내부 callback 으로 호출되는 부분은 소스상에서의 코드 순서를 따지지 않습니다.
실제로 실행될때 callback에 의한 순서대로 처리됩니다.
0 추천
처음에 onCreate에서 사용자가 전에 터치한 항목이 선택되게 만듭니다. setSelection을 사용해서요.

 

사용자가 터치해서 spinner index가 바뀌는 것은 setOnItemSelectedListener로 캐치해서 sharedPreference 등에 저장하면 될 것 같네요.
방귀과장 (18,940 포인트) 님이 2014년 2월 12일 답변
답변감사드립니다. 우선 setSelection을 사용하게 되면..무조건 setOnItemSelectedListener가 불린다는 사실이 문제예요..setSelection으로 index만 고정시켜주면 좋은데 event까지 같이 불리죠..이게 문제입니다.
0 추천

검색하다가 하나님의 은혜로 발견한 건데요.^^ 공유합니다.

출처: https://code.i-harness.com/ko/q/2718c8

3번째 것을 순서대로 넣어 주시면 바로 되네요. 

오늘도 좋은 하루되세요. 

Spinner s = (Spinner)Util.findViewById(view, R.id.sound, R.id.spinner);
s.setAdapter(adapter);
s.setSelection(0, false);
s.setOnItemSelectedListener(listener);
윤폴 (140 포인트) 님이 2018년 6월 18일 답변
지금까지 찾던 정답이네요
감사합니다!
...