使用处理程序&更新视图清理乱七八糟的东西

时间:2011-07-02 15:29:16

标签: android

我有一个扩展LinearLayout的类。我的课程在我的应用程序的许多地方使用。在课堂上我创建了一个处理程序:

Handler updateHandler = new Handler() {
     public void handleMessage(Message msg) {
         // Update image, other items, etc.
    }
};

将此处理程序传递给静态方法并保存,以便在出现某些条件时,可以相应地更新与此句柄关联的所有视图。

问题在于我相信我会无限期地持有对视图的引用。因此,举个例子,我在ExtendedList中使用自定义类,用户折叠显示我的类视图的组。从技术上讲,它已不再使用,但它的处理程序仍会在条件出现时被解雇。

我有更好的方法吗?有没有办法知道视图何时被销毁/处置并且操作系统不再使用它?

BTW:我的目标是SDK版本7。

修改

为了更好地澄清,我将提供一个真实的场景,非常适合我正在尝试做的事情。这是一个人为的例子。

想象一下,你有一张国家的地图。在地图上,您可以看到每个城市的ImageView,显示城市的当前天气。当天气变化时,ImageView需要改变以反映新的天气状况 - 无论是晴天,下雨,下雪等等。

要将此应用于我原来的问题,我会创建一个名为WeatherView的类,其扩展ImageView。在WeatherView里面,我有一个Handler,它被添加到某个静态列表中。在后台线程中并由计时器触发,我使用一个Web服务来提供给定城市的天气。当天气变化时,我会转到我的静态处理程序列表,找出哪些城市需要更新其图像,然后触发“事件”。

现在假设用户切换州或国家/地区,原始城市不再有效。他们的处理程序仍然存在于列表中,因此它们将继续占用内存和资源。

2 个答案:

答案 0 :(得分:0)

  

将此处理程序传递给静态方法并保存,以便在出现某些条件时,可以相应地更新与此句柄关联的所有视图。

伊克。

  

我有更好的方法吗?

在Android中,您的用户界面由一个活动组成,持有视图(暂时忽略片段)。当“某些条件出现”时,无论是什么导致“某些条件”“出现”(ServiceBroadcastReceiver$DEITY的行为,无论如何)都应该通知该事件的活动。反过来,该活动可以通知需要了解该事件的任何观点。

对于此,您不需要每个视图Handler。只需让活动在自定义View上调用方法即可。这样重量更轻,编码更少,更易于维护。

您不需要静态数据成员。虽然您可能希望在活动中维护(非静态)缓存以便于访问需要此事件的那些视图,但该活动已有其视图。这可以避免任何内存泄漏的可能性。


更新(基于已修改的问题)

  

想象一下,你有一张国家的地图。在地图上,您可以看到每个城市的ImageView,显示城市的当前天气。当天气变化时,ImageView需要改变以反映新的天气状况 - 无论是晴天,下雨,下雪等等。

这些都不需要一组Handlers,也不需要静态数据成员。这一切都在一项活动中。

  

在后台线程中并由计时器触发,我使用一个Web服务来提供给定城市的天气。当天气变化时,我会转到我的静态处理程序列表,找出需要更新图像的城市,然后触发“事件”。

如果“后台线程”只是由活动分叉,则不需要静态数据成员,也不需要一堆Handlers。您需要一个Handler,由活动创建/拥有,传递到线程中(并且还在配置更改时在活动实例之间传递),并让线程向Handler发送一条消息。处理程序和活动协作以通知所有ImageViews

如果“后台线程”是IntentService,则会保留相同的模型,除非您将Messenger从活动传递到服务,因为您不能(也不应该)传递通过Handler额外的组件之间的Intent。再一次,您不需要静态数据成员,也不需要每个视图一个Handler

答案 1 :(得分:0)

首先,您不应该在静态字段中保留对contexts / activities / views的引用,以避免内存泄漏。 (见Avoiding Memory leaks

我不知道你想要做什么,但应该可以在每个Activity中创建一个Handler并在Activity被销毁时销毁Handler。为此,请使用Activity生命周期方法。

如果我理解正确,您将更新整个应用程序中的所有视图(在所有活动中)。这在性能方面很可能并不好。

修改

视图应该只显示数据。他们永远不应该实现业务逻辑,比如获取数据。

要解决您的示例,您可以将所有WeatherView存储在HashTable / ArrayList或其他任何内容中,并且您的Activity会定期轮询天气服务。如果天气发生变化,则查看视图使用HashTable获取正确的WeatherView并进行更新。

public class WeatherMapActivity extends ListActivity {

class WeatherData{};


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setListAdapter(new ArrayAdapter<WeatherData>(this,android.R.layout.simple_list_item_1, android.R.id.text1, new ArrayList<WeatherData>()));
}

class WeatherTask extends AsyncTask<String, Void, HashMap<String, WeatherData>> {

    @Override
    protected HashMap doInBackground(String... cities) {
        HashMap<String, WeatherData> data = new HashMap<String, WeatherMapActivity.WeatherData>();

        for (String city : cities) {
            WeatherData fetchedData = null;

            // fetch weather from server

            data.put(city, fetchedData);
        }
        return data;
    }

    protected void onPostExecute(HashMap<String, WeatherData> fetchedData) {

        ArrayAdapter<WeatherData> adapter = (ArrayAdapter<WeatherData>) getListAdapter();
        // now remove/add/update data in the adapter

        //update the list view 
        adapter.notifyDataSetChanged();
    }
}

}