Android应用小部件:内容添加了两次 [英] Android app widget: content added twice

查看:130
本文介绍了Android应用小部件:内容添加了两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个应用程序小部件,打算在其中填充项目列表.我正在尝试通过扩展AppWidgetProvider来实现此简单方法.我看到一些奇怪的行为,其中两次将项目列表添加到父窗口小部件中.

I am writing an app widget which I intend to populate with a list of items. I'm trying to do it the easy way by extending AppWidgetProvider. I am seeing some strange behaviour where the list of items gets added to the parent widget twice.

代码如下:

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    Log.i("MyApp", "onUpdate called");

    DbAdapter dbAdapter = new DbAdapter(context);
    dbAdapter.open();

    final String[] columns = { DbTableCategory.KEY_NAME, DbTableCategory.KEY_CURRENTBAL };
    Cursor cursor = dbAdapter.getDb().query(DbTableCategory.TABLE_NAME, columns, null,
                        null, null, null, null);

    final int n = appWidgetIds.length;
    for (int i = 0; i < n; i++) {

        Log.i("MyApp", "Widget instance " + i);

        final int NUM_ITEMS = 4;

        int id = appWidgetIds[i];
        RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);

        for (int c = 0; c < NUM_ITEMS; c++) {

            // get item info from db
            if (cursor.moveToPosition(c)) {
                RemoteViews itemView = new RemoteViews(context.getPackageName(), R.layout.widget_item);
                itemView.setTextViewText(R.id.widget_item_name, cursor.getString(0));
                itemView.setTextViewText(R.id.widget_item_amnt, cursor.getString(1));

                Log.i("MyApp", "Adding subview for item " + c);
                rv.addView(R.id.widget_container, itemView);
            }
        }

        appWidgetManager.updateAppWidget(id, rv);
    }

    cursor.close();
    dbAdapter.close();

我将四个项目添加到列表中,但是实际上我在小部件中看到了八个项目(相同的四个项目出现了两次).从日志输出中,它告诉我窗口小部件有两个实例(根据appWidgetIds数组,并且ID不同),因此外循环运行两次,内循环运行(针对每个项目)正在按预期运行四次.我不明白这一点,因为我很肯定只将小部件添加到了主屏幕一次.它也不在其他任何主屏幕上-我正在使用默认的HTC Sense启动器.

I add four items to the list, but I actually see eight items in the widget (the same four appearing twice). From the log output, it is telling me that there are two instances of the widget (according to the appWidgetIds array, and the IDs are different), so the outer loop is running twice, and the inner loop (for each item) is running four times as expected. I don't understand this, as I'm positive I've only added the widget to my home screen once. It's not on any of the other home screens either - I'm using the default HTC Sense launcher.

即使我实例化了小部件两次,也要为每个小部件实例创建一个新的RemoteView.我只是不明白为什么一个窗口小部件实例似乎要接收很多东西.我怎么了?

Even if I had instantiated the widget twice, I'm creating a new RemoteViews for each widget instance. I just don't understand why the one widget instance seems to be receiving two lots of items. What am I getting wrong?

附录:当我在模拟器中运行完全相同的代码时,它工作得很好,只报告了一个小部件实例.它仅显示实际电话(HTC Desire,Froyo)上的异常行为.

Addendum: when I run the exact same code in the emulator, it works just fine, with just one widget instance being reported. It's only showing the strange behaviour on the actual phone (HTC Desire, Froyo).

此后,我在文档中注意到了这一点RemoteViews.addView():

I've since noticed this in the documentation for RemoteViews.addView():

如果RemoteViews的使用者可以回收布局,请使用removeAllViews(int)清除所有现有的子级.

In cases where consumers of RemoteViews may recycle layouts, use removeAllViews(int) to clear any existing children.

是否可能从RemoteViews(...)构造函数返回了相同的RemoteViews实例?那可以解释为什么子视图要被添加两次,但是可以解释为什么首先看起来有两个实例.

Could it be that the same RemoteViews instance is being returned from the RemoteViews(...) constructor? That would explain why the child views are being added twice, but it would not explain why there seem to be two instances in the first place.

推荐答案

关于小部件返回两个appWidgetId的第一个问题: 当窗口小部件崩溃时,我遇到过类似的情况(尤其是在配置屏幕上或窗口小部件完全放置之前).桌面应用程序仍将包含有关它的信息,但不会显示它.

The first problem about your widget returning two appWidgetIds: I had similar situations when the widget crash (especially on configuration screens or before the widget was fully placed). The desktop app will still contain information about it, but it won't display it.

第二个(主要)问题可能是由布局视图的回收引起的,我的猜测是R.id.widget_container没有被清理.因此,您可能应该致电:

The second (main) problem is probably caused by recycling of layout views, my guess is that R.id.widget_container is not cleaned up. So you probably should call:

rv.removeAllViews(R.id.widget_container);

在for循环之前.

此外,我建议从游标(cursor.getCount())获取返回的行数,而不要对其进行硬编码(在您的代码中为NUM_ITEMS = 4).

In addition I would suggest getting the number of returned rows from the cursor (cursor.getCount()) and not hard-coding it (NUM_ITEMS = 4 in your code).

这篇关于Android应用小部件:内容添加了两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆