HelloCW
HelloCW

Reputation: 2325

Will the context of Service() cause "This field leaks a context object"?

I have read the articals

This Field leaks context object

This field leaks a context object

Getting a "this field leaks a context object" when passing a context from Main Activity to Java Class via Constructor

The Code private var mService: RecordService? = null show a warning "This field leaks a context object" ? why?

I think that HomeViewModel object will be destroyed after Activity object destroyed, and the mService will be released too, why does Android Studio display "This field leaks a context object" ?

class HomeViewModel(private val mApplication: Application, private val mDBVoiceRepository: DBVoiceRepository) : AndroidViewModel(mApplication) {

    private var mService: RecordService? = null

    private val serviceConnection = object : ServiceConnection {
        override fun onServiceConnected(className: ComponentName, iBinder: IBinder) {
            val binder = iBinder as RecordService.MyBinder
            mService = binder.service
           
        }      
    }

   fun bindService() {
        Intent(mApplication , RecordService::class.java).also { intent ->
            mApplication.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
        }
    }

    fun unbindService() {
        Intent(mApplication, RecordService::class.java).also { intent ->
            mApplication.unbindService(serviceConnection)
            mService?.stopForeground(true)
            mService?.stopSelf()
        }
    }
    ...
}



class RecordService : Service() {
    override fun onBind(intent: Intent): IBinder {
        return MyBinder()
    }

    inner class MyBinder : Binder() {
        val service: RecordService
            get() = this@RecordService
    }

    ...
}

Added Content

To AlphaOne: Thanks!

I still get the warning "This field leaks a context object" when I use the following code, how can I do if I need call RecordService in HomeViewModel?

    class HomeViewModel(private val mApplication: Application, 
                        private val mDBVoiceRepository: DBVoiceRepository,
                        private var mService: RecordService?) : 
             AndroidViewModel(mApplication) {
    
    
    }

And more, the following code is source code of AndroidViewModel , it seems that Android doesn't do extra works for the class AndroidViewModel, it seems that android prevent to display the warning information.

public class AndroidViewModel extends ViewModel {
    @SuppressLint("StaticFieldLeak")
    private Application mApplication;

    public AndroidViewModel(@NonNull Application application) {
        mApplication = application;
    }

    /**
     * Return the application.
     */
    @SuppressWarnings({"TypeParameterUnusedInFormals", "unchecked"})
    @NonNull
    public <T extends Application> T getApplication() {
        return (T) mApplication;
    }
}

Upvotes: 1

Views: 617

Answers (1)

Ravi Kumar
Ravi Kumar

Reputation: 4528

From the Official docs:

A ViewModel must never reference a view, Lifecycle, or any class that may hold a reference to the activity context.

Since the services have their own lifecycle and are managed by Operating Systems, you shouldn't keep its reference inside the ViewModel.

During configuration change, the ViewModel is preserved, so still may have reference to Service and will cause the memory leak.

Upvotes: 3

Related Questions