我写了一个集合小部件来显示主屏幕中的calllogs。 因此可能存在2个接收器:一个是小部件提供者,另一个是调用日志内容观察者。我不确定内容观察者是否是接收者。
Call.xmlAppWidgetProvider在manifest.xml中声明,我需要在这个接收器对象中存储一些数据(稍后在观察者中使用)。
在触发WidgetProvider时构建并注册CallLogContentObserver。调用时会触发观察者。
问题是,当我第一次放置我的小部件时,构建,触发widgetprovide并调用onUpdate,我可以看到在应用程序的主线程中设置了CallLogAppWidgetProvider.mContext和CallLogAppWidgetProvider.mWidgetIds(tid = 8148,pid = 8148)。
但是在进行调用时,会在同一个线程中调用CallLogContentObserver.onChange(tid = 8148,pid = 8148)。在onChange中,mContext具有先前设置的值,但mWidgetIds为null,因此mywidget无法反映calllog的更改。
根据这篇文章:Save data in Broadcast receiver,我的widgetprovider可能在它返回时被销毁,因此它可以解释为什么mWidgetIds为null,但与mContext存储的旧值冲突。那篇文章没有解释为什么我们需要将数据保存在接收器中。
如果widgetprovider被销毁,那么当观察者触发了android如何开始运行观察者的onChange?它是否与lua中的闭包机制相同?为什么mContext可以存储一个值?
如果widgetprovider没有被销毁,那么当观察者运行时为什么mWidgetIds为null?我不确切知道java如何传递原始数组,根据这篇文章:Is an array a primitive type or an object (or something else entirely)?,数组是由jvm创建的运行时类,所以mWidgetIds是一个强引用,整数数组mWidgetIds指向提供者返回后不能是gc,因为至少mWidgetIds指向它。提供者返回时会发生什么?
你能否告诉我这些场景背后发生了什么?任何信息都会被预先准备好,谢谢。
代码如下:
public class CallLogAppWidgetProvider extends AppWidgetProvider {
private static final String TAG = "CallLogAppWidgetProvider";
private ContentObserver mContentObserver = null;
private Handler mHandler = new Handler();
private Context mContext = null; //data to store
private int[] mWidgetIds; //data to store
protected class CallLogContentObserver extends ContentObserver {
public CallLogContentObserver(Handler handler) {
super(handler);
// TODO Auto-generated constructor stub
}
@Override
public void onChange(boolean selfChange) {
AppWidgetManager.getInstance(mContext).notifyAppWidgetViewDataChanged(mWidgetIds, R.id.calllog_list);
}
}
@Override
public void onEnabled(Context context) {
mContext = context; //store data when first place in home screen
mContentObserver = new CallLogContentObserver(mHandler);
context.getContentResolver().registerContentObserver(CallLog.CONTENT_URI, true, mContentObserver);
}
@Override
public void onDisabled(Context context) {
context.getContentResolver().unregisterContentObserver(mContentObserver);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
mWidgetIds = appWidgetIds; //store data when first place in home screen
for (int i = 0; i < appWidgetIds.length; i++) {
Intent intent = new Intent(context, CallLogRemoteViewsService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.calllog_appwidget);
rv.setRemoteAdapter(R.id.calllog_list, intent);
appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
}