1. 程式人生 > >[Android]關於ContentObserver的釋放

[Android]關於ContentObserver的釋放

關於ContentObserver的釋放

 

 

public class MainActivity extends Activity

implements OnClickListener {

 

   private static final String TAG = "MyService";

  

 

   class SettingsObserver extends ContentObserver {

       SettingsObserver(Handler handler) {

           super(handler);

       }

      

       void observe() {

          ContentResolver resolver = getContentResolver();

          resolver.registerContentObserver(

                Settings.System.getUriFor(Settings.System.ALARM_ALERT),

                false, this );

  

          updateSettings();

       }

       @Override

      public void onChange(boolean selfChange) {

          updateSettings();

       }

   }

  

   public void updateSettings() {

   }

  

   public void onClick(View src)

   {

      //2018-9-19

    

         SettingsObserver observer = new SettingsObserver(null);

         observer.observe();

     

   }

  

   @Override

   protected void onCreate(Bundle savedInstanceState) {

      super.onCreate(savedInstanceState);

      setContentView(R.layout.fragment_main);

     

      Button aButton = (Button)findViewById(R.id.button1);

      aButton.setOnClickListener(this);   

   }

 

 

在進行註冊的時候,

resolver.registerContentObserver

呼叫到ContentResolver的registerContentObserver方法

    public final void registerContentObserver(Uri uri, boolean notifyForDescendents,

            ContentObserver observer, int userHandle) {

        try {

            getContentService().registerContentObserver(uri, notifyForDescendents,

                    observer.getContentObserver(), userHandle);

        } catch (RemoteException e) {

        }

    }

 

裡面呼叫到ContentObserver的getContentObserver方法

    public IContentObserver getContentObserver() {

        synchronized (mLock) {

            if (mTransport == null) {

                mTransport = new Transport(this);

            }

            return mTransport;

        }

    }

 

 

    public IContentObserver releaseContentObserver() {

        synchronized (mLock) {

            final Transport oldTransport = mTransport;

            if (oldTransport != null) {

                oldTransport.releaseContentObserver();

//解除引用

                mTransport = null;

            }

            return oldTransport;

        }

    }

new Transport(this);對ContentObserver物件進行了引用

檢視這個內部類

 

    private static final class Transport extends IContentObserver.Stub {

        private ContentObserver mContentObserver;

 

        public Transport(ContentObserver contentObserver) {

            mContentObserver = contentObserver;

        }

 

        @Override

        public void onChange(boolean selfChange, Uri uri, int userId) {

            ContentObserver contentObserver = mContentObserver;

            if (contentObserver != null) {

                contentObserver.dispatchChange(selfChange, uri, userId);

            }

        }

 

        public void releaseContentObserver() {

            mContentObserver = null;

        }

    }

 

 

所以,要釋放ContentObserver物件和Transport物件,必須讓其解除相互引用,即需要呼叫Transport的releaseContentObserver方法。

ContentResolver的unregisterContentObserver就是這樣操作的,裡面observer.releaseContentObserver();中呼叫了Transport的releaseContentObserver方法。

 

    public final void unregisterContentObserver(@NonNull ContentObserver observer) {

        Preconditions.checkNotNull(observer, "observer");

        try {

//得到Transport物件,

            IContentObserver contentObserver = observer.releaseContentObserver();

            if (contentObserver != null) {

                getContentService().unregisterContentObserver(

                        contentObserver);

            }

        } catch (RemoteException e) {

        }

    }

 

所以,應當呼叫ContentResolver的unregisterContentObserver方法進行取消註冊,同時也解除了互相引用,為finalize的呼叫創造前提。不然會出現洩漏。