SQLiteOpenHelper - Cannot access disposed object

124
April 22, 2019, at 9:30 PM

I have a my SQLiteOpenHelper class, which is written as a singleton. I should note that I am not doing this in Java, I am using Xamarin.Android C# to write this.

Here's a snippet from that class:

public class DatabaseHelper : SQLiteOpenHelper
{
    private static readonly string TAG = typeof(DatabaseHelper).FullName;
    private static readonly string _databaseName = "istockdb";
    private static readonly int _databaseVersion = 32;
    private static DatabaseHelper _instance;
    private Context _context;
    private DatabaseHelper(Context context) : base(context, _databaseName, null, _databaseVersion)
    {
        _context = context;
    }
    [MethodImpl(MethodImplOptions.Synchronized)]
    public static DatabaseHelper Instance(Context context)
    {
        // *** Use the application context, which will ensure that ***
        // *** the Activity's context is not accidentally leaked ***
        return _instance ?? (_instance = new DatabaseHelper(context.ApplicationContext));
    }
}

So I have my DatabaseHelper that is a singleton and is used like this within Activities and Services:

Service:

[Service(Name=Text.MobileBackgroundHbService, Enabled = true, Exported = true), IntentFilter(new []{Intents.SyncHeartbeats})]
public class BGHeartbeatService : BaseIntentService
{
    public BGHeartbeatService()
    {
        this._database = DatabaseHelper.Instance(Application.Context);
    }
    protected override void OnHandleIntent(Intent intent)
    {
        if (this._database == null)
            this._database = DatabaseHelper.Instance(Application.Context);
        if (intent.Action.Equals(Intents.SyncHeartbeats)) SyncHeartbeatRecords();
        var broadcastIntent = new Intent(Intents.MobileRefresh);
        SendBroadcast(broadcastIntent);
    }
}

Activity, actually a BaseActivity which all Activities inherit from:

[Activity(Label = "BaseActivity")]
public abstract class BaseActivity : AppCompatActivity
{
    /// <summary>
    /// Reference to the current context.
    /// </summary>
    protected Context _context { get; set; }
    /// <summary>
    /// "Tag" used for Log functionallity.
    /// </summary>
    protected string _tag { get; set; }
    /// <summary>
    /// Reference To <see cref="RemoteSyncServiceConnection"/>
    /// </summary>
    protected RemoteSyncServiceConnection _service_connection;
    /// <summary>
    /// Reference To The Current SessionState.
    /// </summary>
    protected SessionState _session_state;
    /// <summary>
    /// Reference To <see cref="SyncReceiver"/>
    /// </summary>
    protected SyncReceiver _sync_receiver;
    /// <summary>
    /// Base FloatingActionButton.
    /// </summary>
    protected FloatingActionButton _base_fab;
    /// <summary>
    /// Is the Fab Menu Shown / Hid.
    /// </summary>
    protected static bool _is_fab_open;
    protected IConnection _printer_connection;
    protected string _printer_address;
    protected bool _service_required;
    protected bool _receiver_required;
    protected MediaPlayer _media_player;
    protected DatabaseHelper _database;
    /// <summary>
    /// <see cref="IntentFilter"/> for the <see cref="SyncReceiver"/>
    /// </summary>
    protected readonly string[] _intent_filters =
    {
        Intents.AlarmCompleteOrders,
        Intents.AlarmHeartbeats,
        Intents.AlarmPkas,
        Intents.AlarmTrackingScans,
        Intents.MobileRefresh
    };
    #region Lifecycle Methods
    /// <summary>
    /// Application Lifecycle Method.
    /// </summary>
    /// <param name="savedInstanceState"></param>
    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        // *** Initialize Xamarin.Essentials ***
        Xamarin.Essentials.Platform.Init(this, savedInstanceState);
        // *** Initialize the DatabaseHelper ***
        if(this._database == null)
            this._database = DatabaseHelper.Instance(this.ApplicationContext);
    }
}

The DatabaseHelper instance is being disposed of frequently causing either services, or activities to try and access the disposed _database object.

How is this being disposed of and why?

I thought making the _instance static within the DatabaseHelper as well as making the constructor private and forcing the use of the DatabaseHelper.Instance method would keep a single instance of the DatabaseHelper that wouldn't be disposed of between activities and services?

Am I misunderstanding this?

EDIT logcat output from try/catch blocks showing the exception being thrown. The SaveHeartbeat method exists in the base activity.:

protected void SaveHeartbeat(DateTime time, string sourceActivity, [CallerMemberName] string sourceEvent = "")
        {
            try
            {
                var heartbeat = new SmartWarehouse.Shared.Models.Heartbeat(sourceActivity,
                                                                            sourceEvent,
                                                                            this._session_state.CurrentSession.ROWID.ToString());
                this._database.InsertHeartbeat(heartbeat);
            }
            catch (Exception e)
            {
                // TODO: Document Exception
                Util.Tools.Bark(e);
            }
        }

READ ALSO
In Javascript IF-ELSE, IF Statement is not working

In Javascript IF-ELSE, IF Statement is not working

I am trying to work on verifying OTPHere I have two components that are:

15
Fit entire web page on the screen without using scroll bar in css

Fit entire web page on the screen without using scroll bar in css

When I remove scroll bar usingbody{ overflow-y;} in the CSS, I'm unable to see the entire page on the screen

100
What will be the insert query depends on previous data in same table?

What will be the insert query depends on previous data in same table?

I want to insert a row if it's one specific column value is not still availableIf available, i want to update that row

140