android - 小部件问题 : Exiting the main app resets the static variables in the widget

标签 android android-widget

我有一个带按钮的小部件。在我的应用小部件 (TestWidget.java) 中,我有一个私有(private)静态 bool 变量 (buttonClicked) 初始化为 false。

当我单击按钮时, bool 值 buttonClicked 设置为 true。我将 updatePeriodMillis 设置为最小 30 分钟(1800000 毫秒)。

首先 onUpdate 来了:buttonClicked 值为 true。正如预期的那样。

然后我停止我的主应用程序。以下 onUpdates 将 buttonClicked 值显示为 false。

launch --> 06-10 10:55:56.365 4186-4186/com.narb.testwidget I/TESTWID: update setButtonClicked false
1st onUpdate after button click --> 06-10 10:56:11.685 4186-4186/com.narb.testwidget I/TESTWID: setButtonClicked true
onUpdate after main app exit --> I/TESTWID: update setButtonClicked false

这是为什么?

应用小部件 - TestWidget

public class TestWidget extends AppWidgetProvider {
    private static RemoteViews views;
    private static boolean buttonClicked = false;

    static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                                int appWidgetId) {
        appWidgetManager.updateAppWidget(appWidgetId, views);
    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        // Get all ids
        ComponentName thisWidget = new ComponentName(context,
                TestWidget.class);
        int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);

        Log.i("TESTWID", "update setButtonClicked "+buttonClicked);

        views = new RemoteViews(context.getPackageName(), R.layout.test_widget);
        views.setOnClickPendingIntent(R.id.wid_btn_tst, setButton(context));

        for (int appWidgetId : appWidgetIds) {
            updateAppWidget(context, appWidgetManager, appWidgetId);
        }
    }

    public static void setButtonClicked(boolean b){
        buttonClicked = b;
        Log.i("TESTWID", "setButtonClicked "+buttonClicked);
    }

    public static PendingIntent setButton(Context context) {
        Intent intent = new Intent();
        intent.setAction("TEST");
        return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    }

    public static void pushWidgetUpdate(Context context, RemoteViews remoteViews) {
        ComponentName myWidget = new ComponentName(context, TestWidget.class);
        AppWidgetManager manager = AppWidgetManager.getInstance(context);
        manager.updateAppWidget(myWidget, remoteViews);
    }

}

按钮代码 - TestWidgetReceiver

public class TestWidgetReceiver extends BroadcastReceiver{
    private static boolean isButtonON = false;

    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent.getAction().equals("TEST")){
            updateWidgetButton(context, 2);
        }
    }

    private void updateWidgetButton(Context context, int index) {
        RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.test_widget);
        if(index == 2) {
            if(isButtonON) {
                remoteViews.setTextViewText(R.id.wid_btn_tst, "Test Off");
                isButtonON = false;
            }
            else{
                remoteViews.setTextViewText(R.id.wid_btn_tst, "Test On");
                isButtonON = true;
                TestWidget.setButtonClicked(isButtonON);
            }
            //REMEMBER TO ALWAYS REFRESH YOUR BUTTON CLICK LISTENERS!!!
            remoteViews.setOnClickPendingIntent(R.id.wid_btn_tst, TestWidget.setButton(context));
        }

        TestWidget.pushWidgetUpdate(context.getApplicationContext(), remoteViews);
    }

}

list

   <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="Test"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver android:name=".TestWidget">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>

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

        <receiver
            android:name=".TestWidgetReceiver"
            android:label="widgetBroadcastReceiver" >
            <intent-filter>
                <action android:name="TEST" />
            </intent-filter>

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

    </application>

最佳答案

In my app widget (TestWidget.java) I have a private static boolean variable (buttonClicked) initialized to false

static 变量充其量只是一个缓存。

Then I stop my main app.

我不太清楚你的意思。我的猜测是,您的意思是从概览屏幕中删除与您的应用关联的任务。

The following onUpdates shows buttonClicked value as false. Why is that?

如果通过“停止我的主应用程序”,你做了我概述的事情,你将终止你的进程。稍后,例如当您单击应用程序小部件的按钮时,Android 将为您启动一个新的过程,此时您的 static 字段,此时您的静态字段将是其默认值。

I would have thought that widgets have their own memory copy as they continue to run even if the main app has exited?

没有。与您的应用程序小部件关联的 View 将存在于主屏幕中。这不包括您的 TestWidget 代码,它不是主屏幕的一部分。

I'm considering dropping this approach to do an alarmManager with a low refresh time (10 secs).

首先,这在 Android 5.1 及更高版本上是不可能的,因为它会大大耗尽电池电量。其次,它不能保证您的流程会一直存在。

static 变量充其量只是一个缓存。任何应用程序,包括带有应用程序小部件的应用程序,都需要将重要数据存储在其他地方:SharedPreferences、SQLite 数据库、某种其他类型的文件、服务器等。

关于android - 小部件问题 : Exiting the main app resets the static variables in the widget,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50782141/

相关文章:

android - 创建新 Intent 会导致错误

android - 为什么 ProgressBar 在 Android 中交换布局时停止动画?

Android - 从网络浏览器访问麦克风

javascript - 文件错误{代码: 5} trying to use absolute file paths with Meteor 1. 4 Cordova

java - 在 4.4 设备上运行的应用程序的主题问题

android - 将数据库的每一行映射到 ListView 的每一行

android TextView.setText 不适用于简单的小部件

java - 如何将对象添加到 Java 列表中?

android - 在运行时更改自定义键盘中按键的图标

android - RemoteViewsFactory 在数据集为空时调用 getViewAt