广播接收机的生命周期和广播接收机之间共享数据

时间:2015-10-24 14:05:58

标签: java android broadcastreceiver ipc android-lifecycle

我写了一个集合小部件来显示主屏幕中的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);
    }
}

0 个答案:

没有答案