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());
필터 목록을 삭제에 영향을 줄까요? 논리는 지시하지 않을 것입니다 ...
올바르게 사용하고있는 것 같습니다. ArrayList의 코드를 살펴 보았습니다. 아아 당신은 어떤 종류의 필터링을 어댑터에 사용하고 있습니까? (그건 좀 더 복잡한 일이 될 수 있습니다). 어댑터의 초기화와 appState.favoriteAdapter의 선언을 게시 할 수 있습니까? – balazsbalazs
물론입니다. 선언은 매우 간단하며 내 응용 프로그램 클래스에 포함되어 있습니다. public RealmAdapter favoriteAdapter; 실제 초기화는 UI 활동 또는 스레드에서 어댑터에 먼저 액세스 할 스레드에 따라 발생합니다. 그것은 실제로 내가 게시 된 코드의 확장의 이전 버전 : 경우 (appState.favoriteAdapter == NULL) { \t appState.favoriteAdapter = 새로운 RealmAdapter (C, R.layout.list_item, R.layout.realm_entry, appState.favorites) ; } 필터가 있습니다. 게시 할 것입니다. 댓글의 형식이 이상하기 때문에 원본 게시물도 수정합니다. – Eluamous
누구든지 아이디어가 있으십니까? 나는 여전히 손실에 처해있다 ... – Eluamous