1

我正在尝试一些非常简单的代码来让 Android 小部件运行,但没有运气。我环顾四周,并没有找到一个好的答案。

我想要的(现在)只是在触摸小部件时增加一个计数器并显示当前值。

这是我的 AppWidgetProvider:

public class WordWidget extends AppWidgetProvider
{
    Integer touchCounter = 0;

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
    {
        //This is run when a new widget is added or when the update period expires.
        Log.v("wotd",  "Updating " + appWidgetIds.length + " widgets");

        for(int x = 0; x < appWidgetIds.length; x++)
        {
            Integer thisWidgetId = appWidgetIds[x];

            RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);
            remoteViews.setTextViewText(R.id.mainText, touchCounter.toString());

            Intent widgetIntent = new Intent(context, WordWidget.class);
            widgetIntent.setAction("UPDATE_NUMBER");

            PendingIntent widgetPendingIntent = PendingIntent.getBroadcast(context, 0, widgetIntent, 0);

            remoteViews.setOnClickPendingIntent(R.id.widgetLinearLayout, widgetPendingIntent);
            appWidgetManager.updateAppWidget(thisWidgetId, remoteViews);
        }
    }

    @Override
    public void onReceive(Context context, Intent intent)
    {
        Log.v("wotd", "In onReceive with intent=" + intent.toString());
        if (intent.getAction().equals("UPDATE_NUMBER"))
        {
            Log.v("wotd", "In UPDATE_NUMBER");
            touchCounter++;
            RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);
            remoteViews.setTextViewText(R.id.mainText, touchCounter.toString());
        } else
        {
            Log.v("wotd", "In ELSE... going on to super.onReceive()");
            super.onReceive(context, intent);
        }
    }
}

这是我清单的一部分:

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >

    <receiver
        android:icon="@drawable/ic_launcher"
        android:name="com.example.mywidget.WordWidget"
        android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            <action android:name="UPDATE_NUMBER" />
        </intent-filter>

        <meta-data
            android:name="android.appwidget.provider"
            android:resource="@xml/widgetinfo" />
    </receiver>

</application>

日志显示 onReceive() 被放置在主屏幕上后立即被调用,并且在被触摸后,但数量从未增加。我不完全理解小部件是如何工作的,但是它们在 onUpdate() 之后被杀死了吗?所以要做到这一点,我必须使用某种持久存储?

此外,如果我当前添加另一个小部件,即使我只是触摸一个,两者都会显示相同的值并增加。有没有办法让每个小部件都有自己的计数器?

谢谢!

4

1 回答 1

12

其实你已经回答了你的问题。但是让我们澄清一些事情:

A. 只要 AppWidgets 在主屏幕上,它们就不会被杀死。但它们不属于你。它们在主应用程序的进程中运行。更具体地说,他们的视图在主应用程序的进程中运行,这就是为什么您会看到您的小部件但它没有按照您的预期执行,这就是我们使用 RemoteViews 而不是 Views 来更新它们的原因.

B. 另一方面,AppWidgetProviders(在您的情况下是 WordWidget 类)在 onReceive 方法完成后立即被销毁。每次调用 onReceive 方法时,它们中的所有变量都会重新初始化。这就是为什么你的人数永远不会增加的原因。AppWidgetProvider 的目的是更新小部件的 RemoteViews 并通知您的应用程序已注册的广播已到达。

C. AppWidgetProvider 的 onUpdate 方法为您提供了一个包含必须更新的小部件 Id 的数组。这是唯一可用于获取小部件实例数量及其 ID 的代码点。由于 RemoteViews 没有办法从小部件的视图中获取一些有用的值(例如,您无法从 TextView 读取计数器值),因此您必须使用提供的信息并坚持每个小部件 id 的计数器值。当下一个 onUpdate 被调用时,您从存储中读取值,增加它,使用新值更新小部件,然后将新值存储回来。

D. 如果您的小部件在更新自身时必须做很多事情或减慢速度(如网络),您应该考虑为此使用服务。但是在您的情况下(增加数字),只要您将计数器保存在持久存储或其他地方,您的方法就可以了。

最后我注意到,在您的 onReceive 覆盖中,只有在您没有收到“UPDATE_NUMBER”操作时才调用“super.onReceive”。这不是一个好的做法,除非有很好的理由(那是另一回事)总是调用 super.onReceive 作为覆盖中的第一个或最后一个命令。

希望这可以帮助...

于 2012-05-13T15:48:11.067 回答