2012-01-05 3 views
4

Android의 ArrayAdapter 사용자 정의 구현에 이상한 문제가 있습니다. 배경을 제공하기 위해 현재 스크롤 위치를 유지하면서 ListView의 내용을 업데이트하려고합니다.Android ArrayAdapter가 지워지지 않습니까?

스레드를 실행하여 ListView에 표시된 데이터를 업데이트하는 서비스가 있습니다. 이 데이터는 ArrayList에 저장되며이 ArrayList는 ListView에 대한 사용자 정의 ArrayAdapter를 생성하는 데 사용됩니다. ListView의 항목을 누를 때도 어댑터가 업데이트됩니다 (항목 추가 또는 제거). 어떤 유형의 변경이있을 때마다 새 어댑터를 작성한 다음이 새 어댑터를 ListView로 설정했습니다. 이 작동하지만 ListView 때마다 맨 위로 스크롤 할 일으켰습니다. 내 적용의 본질을 감안할 때 이는 바람직하지 않습니다. ListView의 현재 스크롤 된 위치는 업데이트간에 유지 관리해야합니다.

새 어댑터를 만드는 대신 어댑터의 clear() 메서드를 사용하여 업데이트해야하는 어댑터를 지우고 어댑터의 add() 메서드를 사용하여 어댑터의 항목을 다시 작성하기 시작했습니다. 이 두 가지 방법 모두 어댑터에서 호출됩니다. 어댑터는 생성자에서 notifyDataOnChange를 모두 설정하므로 매번 notiftyDatasetChanged()를 수동으로 호출 할 필요가 없습니다. (수동으로 호출해도 문제가 없지만).

public class RealmAdapter extends ArrayAdapter<Realm> 
{ 
    Context c; 

    public RealmAdapter(Context context, int resource, int textViewResourceId) 
    {    
     super(context, resource, textViewResourceId); 
     setNotifyOnChange(true); 
     c = context; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) 
    { 
     ... 
    } 
... 
} 

길고도 짧은 이야기, 여기에 내 문제입니다 :

여기 내 사용자 지정 어댑터의 모습입니다. 어댑터에서 clear()를 호출하면 어댑터가 지워지지 않습니다.

다음은 내 스레드의 내 onPostExecute에서 발췌 한 스 니펫입니다. UI 스레드에서 업데이트되도록 여기에 넣으려고합니다. 또한이 정확한 코드를 내 UI 활동의 개인 메서드에 복사했습니다. 이 코드는 두 장소에서 작동하지 않습니다

appState.favoriteAdapter.clear(); 
Log.d(LOG_TAG, "COUNT: " + appState.favoriteAdapter.getCount()); 
for(Realm r : appState.favorites) { 
    appState.favoriteAdapter.add(r); 
} 
Log.d(LOG_TAG, "COUNT: " + appState.favoriteAdapter.getCount()); 

를 예를 들어, 위의 어댑터가 바로 맑은 후 getCount()을 (를 호출, 그것에서 3 개 항목이 있다면) 마찬가지로 0 대신 3을 반환, appState.favorites ArrayList에 2 개의 항목 만있는 경우 루프 이후의 getCount()는 2가 아닌 3을 반환합니다. 어댑터가 이러한 호출에 응답하지 않으므로 어떤 방식 으로든 업데이트 할 수 없습니다. 나중에 도움이 될만한 Logcat을 게시 할 수는 있지만 예외 나 유용한 내용은 표시되지 않습니다.

몇 시간 동안 내 머리를 아프게 한 후 어댑터가 변경하는 방법에 대한 호출에 응답하지 않는 것 같습니다. 빈 ArrayList를 어댑터의 super() 호출에 전달하려고 시도했지만 도움이되지 않습니다. 뭔가 빠졌거나 ArrayAdapter를 잘못 사용하고 있습니까? 나는 모든 것을 조사해 보았고 기본 배열을 수정하고 업데이트를 기대하거나 (또는 ​​어댑터에 대한 케이스 설정에서) notifyDatasetChanged()를 호출하지 않고 지원되지 않는 기본 컬렉션에 대한 작업.

favoriteAdapter의 선언은 매우 간단하고 내 응용 프로그램 클래스에 포함되어

if(appState.favoriteAdapter == null) { 
    appState.favoriteAdapter = new RealmAdapter(c, R.layout.list_item, R.layout.realm_entry, appState.favorites); 
} 
else { 
    appState.favoriteAdapter.clear(); 
    Log.d(LOG_TAG, "COUNT: " + appState.favoriteAdapter.getCount()); 
    for(Realm r : appState.favorites) { 
     appState.favoriteAdapter.add(r); 
    } 
    Log.d(LOG_TAG, "COUNT: " + appState.favoriteAdapter.getCount()); 
} 

위의 코드는 모두에 : 여기

public RealmAdapter favoriteAdapter; 

위에서 favoriteAdapter의 초기화이다 내 UI 스레드 및 새로 고침 된 데이터를 다운로드하는 스레드필터 위의 코드 밑에

는 장소에 배치되어

if(appState.favoriteAdapter != null && RealmSelector.realmFilter != null)     appState.favoriteAdapter.getFilter().filter(RealmSelector.realmFilter.getText().toString()); 

필터 목록을 삭제에 영향을 줄까요? 논리는 지시하지 않을 것입니다 ...

+0

올바르게 사용하고있는 것 같습니다. ArrayList의 코드를 살펴 보았습니다. 아아 당신은 어떤 종류의 필터링을 어댑터에 사용하고 있습니까? (그건 좀 더 복잡한 일이 될 수 있습니다). 어댑터의 초기화와 appState.favoriteAdapter의 선언을 게시 할 수 있습니까? – balazsbalazs

+0

물론입니다. 선언은 매우 간단하며 내 응용 프로그램 클래스에 포함되어 있습니다. public RealmAdapter favoriteAdapter; 실제 초기화는 UI 활동 또는 스레드에서 어댑터에 먼저 액세스 할 스레드에 따라 발생합니다. 그것은 실제로 내가 게시 된 코드의 확장의 이전 버전 : 경우 (appState.favoriteAdapter == NULL) { \t appState.favoriteAdapter = 새로운 RealmAdapter (C, R.layout.list_item, R.layout.realm_entry, appState.favorites) ; } 필터가 있습니다. 게시 할 것입니다. 댓글의 형식이 이상하기 때문에 원본 게시물도 수정합니다. – Eluamous

+0

누구든지 아이디어가 있으십니까? 나는 여전히 손실에 처해있다 ... – Eluamous

답변

1

사용자 지정 ArrayAdapter에 필터가 적용되어 있습니다. 분명히 이것은 어댑터 자체에서 항목을 추가하고 제거하는 것을 방해합니까? 내 코드에이 메소드를 추가하면 현재 작동 중입니다.

if(appState.favoriteAdapter != null && realmFilter != null) { 
    appState.favoriteAdapter.getFilter().filter(realmFilter.getText().toString()); 
} 

누군가가이 문제의 원인을 설명 할 수 있다면 좋겠어요. 필자는 필터가 어댑터의 하위 집합을 선택하기위한 것이라고 생각했습니다. 내 테스트에서 필자는 필터에 사용 된 텍스트 상자를 비워 둠으로써 실제 필터 텍스트를 적용하지 않아야했습니다. 다시 말하지만, 누군가가 무슨 일이 일어나고 있는지 알면 나에게 이것이 왜 내가 알고 싶어하는 문제를 해결하는지 설명 할 수 있습니다.

관련 문제