在 AppWidgetProvider 中执行 UnregisterReceiver() 时出错
Posted
技术标签:
【中文标题】在 AppWidgetProvider 中执行 UnregisterReceiver() 时出错【英文标题】:Error when executing UnregisterReceiver() in AppWidgetProvider 【发布时间】:2018-12-06 01:51:05 【问题描述】:在我的应用程序中,我正在注册一个广播接收器,如果在小部件更新时没有网络连接,它会监听连接变化,并且如果在更新时有互联网连接,我想取消注册它。我正在努力解决的问题是让相同的接收器实例取消注册它,因为当应用程序更新时,会构建一个新的 appwidgetprovide 实例,所以我没有对该实例的引用。我尝试将其存储在 SharedPreferences 中,但这给了我一个错误:接收器未注册。
public void decideBroadcastState(Context context)
// get the network receiver from shared preferences
preferencesReceiver = Preferences.getSavedObjectFromPreference(context, Constants.SHARED_BROADCAST, this.getBroadcastKey(), NetworkReceiver.class);
// If there is an internet connection, turn off the broadcast
if(isInternetConnection)
// stop listening for a connectivity change
// If a broadcast was registered, cancel it.
if(preferencesReceiver != null)
context.unregisterReceiver(preferencesReceiver);
Preferences.deleteCurrencyPref(context, Constants.SHARED_BROADCAST, this.getBroadcastKey());
// If there's no internet connection, create a new broadcast
else
// Create an intent that will look for a network connection, and will update the
// widgets, once there is one.
// if it doesn't exist, create one.
if(preferencesReceiver == null)
final String connectivityChange = "android.net.conn.CONNECTIVITY_CHANGE";
IntentFilter intentFilter = new IntentFilter(connectivityChange);
// register it
// mReceiver is a new instance of the broadcast
context.getApplicationContext()
.registerReceiver(mReceiver, intentFilter);
// Store it in preferences
Preferences.saveCurrencyPref(context, Constants.SHARED_BROADCAST, this.getBroadcastKey(), mReceiver);
这是我的 Preferences 类:
public class Preferences
// Write the prefix to the SharedPreferences object for this widget.
public static void saveCurrencyPref(Context context, String filePlace, String preferenceKey, Object anObject)
SharedPreferences sharedPref = context.getSharedPreferences(filePlace, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
Gson gson = new Gson();
String json = gson.toJson(anObject);
editor.putString(preferenceKey, json);
editor.apply();
// Read the prefix from the SharedPreferences object for this widget.
public static <NetworkReceiver> NetworkReceiver getSavedObjectFromPreference(Context context, String filePlace, String preferenceKey, Class<NetworkReceiver> classType)
SharedPreferences sharedPreferences = context.getSharedPreferences(filePlace, Context.MODE_PRIVATE);
if (sharedPreferences.contains(preferenceKey))
final Gson gson = new Gson();
String json = sharedPreferences.getString(preferenceKey, "");
NetworkReceiver obj = gson.fromJson(json, classType);
return obj;
return null;
static void deleteCurrencyPref(Context context, String filePlace, String preferenceKey)
SharedPreferences sharedPref = context.getSharedPreferences(filePlace, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.remove(preferenceKey);
editor.apply();
【问题讨论】:
【参考方案1】:当使用GSON
在SharedPreferences
中存储和检索对象时,您正在序列化和反序列化该对象。这样做不会为您提供相同的对象实例,而是为您提供具有相同值的对象副本。如果您想了解更多有关其工作原理的信息,请搜索序列化和 Java 堆。
您应该能够将BroadcastReceiver
存储在appWidgetProvider
的静态字段中。我不知道你到底在做什么,但你不应该需要超过 1 个 BroadcastReceiver
实例。
【讨论】:
【参考方案2】:首先,AppWidgetProvider 是一个非常强大的 BroadcastReceiver,因此他的生命周期与 BroadcastReceiver 相同。 BroadcastReceiver 主要存活 15 秒(如果你不使用 goAsync()),在主线程上完成他的工作,然后死掉(所以你的进程也会死掉)。因此,在 AppWidgetProvider 中注册一个动态 BroadcastReceiver 并不是最好的主意,因此 Android 为您提供了使用 Service(带有 Android O 通知的前台服务)来注册您的动态接收器并监听某种事件。
【讨论】:
以上是关于在 AppWidgetProvider 中执行 UnregisterReceiver() 时出错的主要内容,如果未能解决你的问题,请参考以下文章
使用匕首 2 在 Kotlin 中的 AppWidgetProvider 中的字段注入
扩展 AppWidgetProvider 的 Widget 中是不是可以使用 TextView Marquee?
AppWidgetProvider - 每次对任何 AppWidget 文件进行更改时都会触发 onUpdate 吗?