2012-02-17 5 views
0

문제 : 활동 A는 ListAdapter을 포함하는 ListView이고 어댑터의 항목을 클릭하면 활동 B가됩니다. 활동 B에는 웹에서 새 항목 (또는 여러 항목)을 가져 오는 버튼이 있습니다 (AsyncTask 사용). 눌렀을 때 활동 A에 표시된 목록에 추가합니다. B에서의 작업은 ProgressDialog에 의해 차단되지 않으므로 B가 데이터 가져 오기를 시작한 AsyncTask 전에 사용자가 A로 다시 이동할 수 있습니다.활동의 어댑터를 다른 활동에서 어떻게 업데이트 할 수 있습니까?

그래서 난 B.

I가 B에서의 버튼을 누르면 A. 의해 ListView 표시 정적 데이터 클래스 C가

에서의 어댑터를 갱신하는 방법을 필요로, 그 값을 추가 C. 그 클래스는 또한 정적 필드로 A에서 어댑터를 가지고 있지만,이 Context에서 메모리 누수가 생각하고, 그 나쁜 것입니다. 이 문제를 해결하기위한 첫 번째 아이디어는 C에서 고정 어댑터를 제거하고 A onResume() (어댑터의 데이터가 C와 다른 경우) 어댑터의 데이터를 다시 C로로드하고 notifyDatasetChanged()입니다. 대부분의 경우 작동하지만 사용자가 웹에서 데이터를 가져 오기 전에 B에서 A로 돌아 가면 데이터가 가져 오기 전에 onResume()이 오기 때문에 어댑터가 업데이트되지 않습니다.

질문 : A의 어댑터를 B에서 업데이트하는 더 좋은 방법이 있습니까?

답변

0

정적 참조를 어댑터에 저장하지 마십시오. 그것은 실제로 기억을 누설하고 나쁘게 행동 할 것입니다.

처음 오해 한 것 같습니다.

먼저 용액

미녀 용액은 데이터를 저장하기 위해 콘텐츠 제공자를 구현 모두에 콘텐츠 제공자를 조회 B.가 컨텐트 프로 바이더를 이용하여 B의 데이터를 갱신한다 : 여기서 업데이트 응답이다. insert() 을 사용하고 contentProvider.query()를 사용하여 데이터를 읽습니다. 예를 들어 데이터베이스에서 지원하는 경우 SQLiteCursor를 반환하고 콘텐츠 공급자의 메모리에 저장하는 경우 MatrixCursor를 반환합니다. (CursorLoader없이)

기본 단계 : (A)의에서 onCreate에서

  1. 당신은 URI이 URI는 사용자가 설정 한 몇 가지 방식을 사용된다 ContentResolver.registerContentObserver(uri, true, this)를 사용하여 contentobserver로 자신을 등록합니다.
  2. onCreate of A에서 ContentResolver.query(uri, projection, selection, selectionArgs, sortOrder)을 사용하여 contentprovider를 쿼리하여 데이터를 가져옵니다. 여기서 projection, selection, selectionArgs 및 sortOrder는 contentprovider (어쩌면 null 일 수 있음)가 될 수 있습니다. Uri는 쿼리하려는 데이터를 참조하며 선택 사항입니다.
  3. B에 데이터가로드되면 ContentResolver.insert()이라고 부릅니다. 콘텐츠 공급자의 insert에서 ContentResolver.notifyChange (Uri uri, null, null)을 호출합니다. 여기서 uri는 1 단계에서 사용한 URI입니다.
  4. A에서 onChange (boolean selfChange)를 구현하고 호출시 콘텐츠 공급자를 다시 쿼리합니다.

CursorLoaders를 사용하는 경우 registerContentObserver를 전혀 호출 할 필요가 없습니다. 변경 사항을 알릴 때 자동 다시 쿼리가 있으므로 로더에 새 커서가 수신됩니다.

두 번째 해답 데이터를 처리하는 싱글 톤 개체를 구현하는 것이 덜 바람직합니다. 뭔가 같은 :

  1. 클래스를 구현

    public class DataHolder { 
        private static DataHolder sDataHolder; 
    
        private String data = ""; // Data represented by string. 
        public DataHolder getInstance() { 
         if (sDataHolder == null) { 
          sDataHolder = new DataHolder() 
         } 
         return sDataHolder; 
        } 
    
        private DataHolder() {} // Hidden constructor 
    
        public void setData(final String data) { 
         mData = data; 
    
         for (DataListener listener: mDataListeners) { 
          listener.onDataChanged(mData); 
         } 
        } 
    
        public void registerListener(DataListener listener) { 
         mDataListeners.add(listener); 
        } 
    
        public String unregisterListener(DataListener listener) { 
         mDataListeners.remove(listener); 
        } 
    
        public String getData() { 
         return mData; 
        } 
    
        public static interface DataListener { 
         public void onDataChanged(String data); 
        } 
    } 
    
  2. 이 확인
  3. 읽기 DataListener을 구현하고 변경시 수행 된 경우이 설정되어 있는지 확인 DataListener의 onStart()에서 데이터를 업데이트 B는 DataHolder.getInstance().getData()을 사용하여 생존했습니다.
  4. A의 onCreate/onStart에 청취자 등록 DataHolder.getInstance().registerListener(this);을 사용하여 청취자가 데이터를 업데이트하도록하십시오. A의들의 OnDestroy에서
  5. 등록 취소 리스너가 중지시 데이터를 설정 DataHolder.getInstance().unregisterListener(this)
  6. 을 사용하고 synchronized String registerListenerAndGetValue() 경우에 void registerListener()을 변경하여 DataHolder.getInstance().setData(data)

는 또한 두 번째 솔루션은 완전히 스레드에 안전 할 수 있습니다 사용하여 B의 모든 청취자 신호/또한 setValue를 동기화합니다.

의 오해에 기반 올드 대답

일반적인 결과 처리에 대한 나의 오래된 대답은 꽤 질문에 대답하지 않았다, 그러나 그것은이었다

당신이 활동 A를 다시 데이터를 전송하려는 경우 B는,268을 사용하여 완료되면

  1. 항상 설정 startActivityForResult (Intent intent, int requestCode)
  2. 결과와 B를 시작 : 다음을 수행해야합니다 당신은 그래서 당신은 예를 들어의 경우에만 savedInstanceState == null 그것을 수행하여 처음에 데이터를 가져 추가 할 수있는 추가로 onActivityResult (int requestCode, int resultCode, Intent data)

을 구현하여 다시 올 때 그 결과를 처리

  • 에서 onCreate() .

  • +0

    데이터가 여전히 활동 B에서 페치되는 동안 사용자는 BACK 버튼을 누른 다음 ('onActivityResult()'의 결과 코드로 'RESULT_CANCEL'을 얻을 수 있음) 어떻게 진행할 것입니까? – Luksprog

    +0

    바로. B의 데이터는 AsyncTask에서 페치되고 끝나면 C의 데이터를 설정합니다. 사용자가 B에서 BACk를 누르면 활동이 종료되지만 데이터는 여전히 AsyncTask에서 페치됩니다. – hgm

    +0

    나는 그 질문을 오해했다. 그 죄송합니다. 편집 된 답변에 두 가지 해결책을 추가했습니다. –

    0

    시도 mListView.invalidate();

    * *이 자바 문서

    전체보기를 무효화 호출. 뷰가 표시되면 미래의 어느 시점에서 onDraw (android.graphics.Canvas)가 호출됩니다. 이것은 UI 스레드에서 호출해야합니다. UI가 아닌 스레드에서 호출하려면 postInvalidate()을 호출하십시오.

    관련 문제