如何从其他活动更新活动的适配器?

问题描述:

问题:活动A是一个ListView,其中包含ListAdapter,并且单击适配器的任何项目都会导致活动B.活动B有一个按钮,用于从Web中获取一个或多个新项目(使用AsyncTask)和将其添加到按下时由活动A显示的列表中。来自B的操作不会被ProgressDialog阻止,因此用户可以在B开始的AsyncTask完成提取数据之前移回到A.如何从其他活动更新活动的适配器?

所以我需要从B.

我有在ListView由A.当在B点的按钮被按下时显示静态数据的C类更新的适配器的方式,增加该值C.这个类也有来自A的适配器作为静态字段,但我认为这会泄漏来自Context的内存,这很糟糕。我确定这的第一个想法是去除C和每次静态适配器A onResume()(如果适配器上的数据是从我都位于C不同),我从C的数据加载又进了适配器和notifyDatasetChanged()。那么,大多数情况下它都能正常工作,但是如果用户在B从Web获取数据之前从B返回A,那么适配器不会更新,因为onResume()在获取数据之前就已经出现了。

问:有没有的B更新的适配器的更好的办法?

不要保存到适配器静态引用。它确实会泄漏记忆并且表现不好。

看来我误解了第一次。下面是一个更新的答案:

首先解决

最漂亮的解决方案是实现对数据存储的内容提供商和查询的内容提供商在A与B两者使用的ContentProvider更新B中的数据。插入() 和读取使用contentProvider.query(),如果它是由数据库或MatrixCursor支持,如果你只是将它保存在内存中的内容提供商返回例如SQLiteCursor数据。

的基本步骤(无CursorLoader):

  1. 在A的的onCreate你自己注册为在那里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()。在您的ContentProvider的insert你打电话ContentResolver.notifyChange (Uri uri, null, null)其中URI是URI您在步骤1
  4. 用于实现一个的onChange(布尔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. 让一个工具的DataListener
  3. 阅读和的DataListener的onStart()更新数据,以确保如果变化的时候做到了它被设置B还活着使用​​。
  4. 使用DataHolder.getInstance().registerListener(this);在A的onCreate/onStart中注册侦听器让侦听器更新数据。
  5. 在A的的onDestroy注销监听器/的onStop使用DataHolder.getInstance().unregisterListener(this)
  6. 设定数据,并使用DataHolder.getInstance().setData(data)

另外请注意,你可以让第二个解决方案完全线程安全的,通过改变void registerListener()synchronized String registerListenerAndGetValue()中频信号B中任意监听器你也使setValue同步。

基于一种误解老答案

我以前的答案一般结果的处理并没有完全回答这个问题,但它是:

如果你想将数据发送回一个活性的你应做到以下几点:

使用乙完成后
  1. 始终以startActivityForResult (Intent intent, int requestCode)
  2. 将结果入门C
  3. 处理的结果,当你回来一个通过实施onActivityResult (int requestCode, int resultCode, Intent data)

作为补充,你可以添加,所以你只有这样它才savedInstanceState == null在例如取A中的第一次数据的onCreate() 。

+0

用户可以按下BACK按钮(并在'onActivityResult()'中获得'RESULT_CANCEL'作为结果代码),而数据仍然在activity B中获取。他将如何继续进行这种情况?确切地说, – Luksprog 2012-02-17 19:19:02

+0

。 B中的数据将在AsyncTask中获取,并且在数据结束时将数据设置为C.如果用户按下B中的BACk,则活动将结束,但数据仍将在AsyncTask中获取。 – hgm 2012-02-17 19:23:31

+0

我误解了这个问题。对不起。我在编辑的答案中添加了两个解决方案。 – 2012-02-17 19:49:37

尝试调用mListView.invalidate();

* * java-doc的

无效整个视图。如果视图可见,onDraw(android.graphics.Canvas)将在未来的某个时间点被调用。这必须从UI线程调用。要从非UI线程调用,请调用postInvalidate()