0

I wrote a collection widget to show calllogs in home screen. So there may have 2 receivers exist: one is widget provider the other is call log content observer. Im not sure whether content observer is a receiver or not.

CallLogAppWidgetProvider is declared in manifest.xml and I need to store some data in this receiver object (for using later in observer).

CallLogContentObserver is constructed and registered when WidgetProvider triggered. Observer is triggered when calls are made.

The problem is, when I first place my widget, widgetprovide is constructed, triggered and onUpdate is called, I can see CallLogAppWidgetProvider.mContext and CallLogAppWidgetProvider.mWidgetIds is set in app's main thread(tid=8148,pid=8148).

but when calls are made, CallLogContentObserver.onChange is called in the same thread(tid=8148,pid=8148). Inside onChange, mContext has the value that set previously but mWidgetIds is null, so mywidget could not reflect calllog's changes.

According to this post: Save data in Broadcast receiver , my widgetprovider may be destroyed when it returned, so it could explain why mWidgetIds is null, but conflict with mContext stored old value. And that post did not explain why we need persist our data in receivers.

If widgetprovider is destroyed, then when observer triggered how did android start to run observer's onChange? Is it the same mechanism like closures in lua? Why mContext can store a value?

If widgetprovider is not destroyed, then why mWidgetIds is null when observer runs? I dont know exactly how java passes primitive array, according to this post: Is an array a primitive type or an object (or something else entirely)? , arrays are runtime classes created by jvm, so mWidgetIds is a strong reference, the integer array mWidgetIds points to can not be gc after provider returned, because at least mWidgetIds points to it. What happend when provider returned?

Could you please tell me what on earth happend behind thses scenes? Any information will be precitated, thank you.

code is below:

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);
    }
}
Community
  • 1
  • 1
梁梁梁
  • 41
  • 4
  • Can you please be more concise? – e4c5 Oct 24 '15 at 14:54
  • ok, the focus is why two variables from the same receiver object behavior differently when used outside the containing receiver object? mContext can store its value but mWidgetIds can not. – 梁梁梁 Oct 26 '15 at 02:34

0 Answers0