E/SQLiteLog: (283) 从 WAL 文件恢复帧

E/SQLiteLog: (283) recovered frames from WAL file

我每次启动我的应用程序时都会出错。

E/SQLiteLog: (283) recovered 22 frames from WAL file /data/data/com.dmitrysimakov.kilogram/databases/androidx.work.workdb-wal

应用程序运行良好,但我想知道为什么会出现此错误。 databases/androidx.work.workdb-wal 是个工人日记。我使用 Worker 预填充我的数据库。

Room.databaseBuilder(app, KilogramDb::class.java, "kilogram.db")
            .addCallback(object : RoomDatabase.Callback() {
                override fun onCreate(db: SupportSQLiteDatabase) {
                    super.onCreate(db)
                    val request = OneTimeWorkRequestBuilder<SeedDatabaseWorker>().build()
                    WorkManager.getInstance().enqueue(request)
                }
            })
            .fallbackToDestructiveMigration()
            .build()

此消息表示数据库在退出前未关闭,因此 WAL 文件未正确清理。

因此,当应用程序启动时,它意识到它需要清理 WAL 文件,然后这样做,但发出错误,因为它可能表明存在严重问题。

要解决此问题,您需要在完成后关闭数据库。

您可能会对此感兴趣Richard Hipp 是 SQLite 的主要负责人,如果您还不知道的话) Continuous recovery of journal

我正在使用绑定服务连接到房间数据库,所以我在我的 RoomService.onDestroy() 方法中使用此代码:

  @Override
  public final void
  onDestroy()
  {
    super
    .onDestroy();

    if(roomDatabase != null)
    {
      if(roomDatabase
         .isOpen())
      {
        roomDatabase
        .close();
      }
    }
  }

如果您在 Application 单例或 Activity 中创建 RoomDatabase 实例,您可以在那里做同样的事情(在相应的 onDestroy() 方法中)。

为方便起见,这里是我在 MainActivity class 中用于关闭绑定服务中的数据库的代码:

  @Override
  protected final void
  onDestroy()
  {
    super.onDestroy();

    if(isFinishing())
    {
      if(mainViewModel != null)
      {
        mainViewModel
        .onDestroy();
      }
    }
  }

MainViewModel.onDestroy() 中,我向绑定服务发送消息以关闭 roomDatabase,然后解除绑定 roomService

  public final void
  onDestroy()
  {
    if(contextWeakReference != null)
    {
      final Context
      context =
      contextWeakReference
      .get();

      if(context != null)
      {
        if(roomServiceConnection != null)
        {
          if(boundToRoomService)
          { 
            sendDBCloseMessageToRoomService();

            context
            .unbindService
            (roomServiceConnection);
          }
        }
      }
    }
  }

  private void
  sendDBCloseMessageToRoomService()
  {
    try
    {
      final Message message =
      Message.obtain
      (null, MSG_DB_CLOSE);

      if(message != null)
      {
        if(messengerToRoomService != null)
        {
          messengerToRoomService
          .send(message);
        }
      }
    }
    catch(final RemoteException e)
    {
      e.printStackTrace();
    }
  }

RoomService 中,我收到要关闭的消息 roomDatabase:

  public class RoomService
  extends Service
  {
    @NonNull @NonNls public static final
    String DATABASE_NAME = "room_database";

    public static final int MSG_DB_CLOSE = 108;

    @Nullable public RoomDatabase roomDatabase;

    private final IBinder roomBinder = new Binder();
    private WeakReference<Context> contextWeakReference;

    @Nullable public Messenger messengerFromRoomService;
    @Nullable public Messenger messengerToRoomService;

    private static class RoomServiceHandler
    extends Handler
    {
      @Nullable private final 
      WeakReference<RoomService> roomServiceWeakReference;

      RoomServiceHandler
      (@Nullable final
       RoomService service)
      {
        if(service != null)
        {
          roomServiceWeakReference =
          new WeakReference<RoomService>
          (service);
        }
        else
        {
          roomServiceWeakReference = null;
        }
      }

      @Override
      public final void
      handleMessage
      (@Nullable final
      Message message)
      {
        if(message != null)
        {
          final int what =
          message.what;

          switch(what)
          {
            case MSG_DB_CLOSE:
            {
              handleDBCloseMessage
              (message);
              break;
            }
          }
        }
      }

      private void
      handleDBCloseMessage
      (@Nullable final
       Message message)
      {
        if(message != null)
        {
          final RoomService
          service =
          roomServiceWeakReference
          .get();

          if(service != null)
          {
            if(service
               .roomDatabase != null)
            {
              if(service
                 .roomDatabase
                 .isOpen())
              {
                service
                .roomDatabase
                .close();    
              }
            }
          }
        }
      }
    }

    @Override
    public final void
    onCreate()
    {
      super.onCreate();

      // initialize application context weak reference
      final Context
      applicationContext =
      getApplicationContext();

      if(applicationContext != null)
      {
        contextWeakReference =
        new WeakReference<Context>
        (applicationContext);

        // initialize database
        roomDatabase =
        Room
        .databaseBuilder
        (applicationContext,
        MyRoomDatabase.class,
        DATABASE_NAME)
        .build();

        if(roomDatabase != null)
        {
          // initialise your DAO here
          yourDao =
          roomDatabase
          .yourDao();
        }
      }

      final RoomServiceHandler
      roomServiceHandler =
      new RoomServiceHandler(this);

      if(roomServiceHandler != null)
      {
        messengerToRoomService =
        new Messenger(roomServiceHandler);
      }
    }

    @Nullable
    @Override
    public final IBinder
    onBind
    (@Nullable final
    Intent intent)
    {
      IBinder result = null;

      if(messengerToRoomService != null)
      {
        final IBinder
        roomBinder =
        messengerToRoomService
        .getBinder();

        if(roomBinder != null)
        {
          result = roomBinder;
        }
      }
      return result;
    }
  }