Exercício: Usar o SQLite de maneira assíncrona

Concluído

O aplicativo funciona bem, mas se o banco de dados contiver muitas linhas, a interface do usuário poderá ficar sem resposta enquanto o aplicativo executa consultas de banco de dados e outras operações. Neste exercício, você converterá o aplicativo da API Síncrona do SQLite para a versão assíncrona. Assim, seu aplicativo será sempre responsivo, independentemente de quantas consultas você fizer ao banco de dados.

Criar uma conexão assíncrona

  1. Abra o arquivo PersonRepository.cs no projeto Pessoas.

  2. Modifique a definição Init do método para ser async. Altere o tipo de retorno do método para Task.

  3. Altere a propriedade conn para um SQLiteAsyncConnection e atualize o código no método Init que inicializa a conexão.

  4. Substitua a chamada para o método síncrono CreateTable pelo método assíncrono CreateTableAsync.

    O script concluído deverá ter esta aparência:

    private SQLiteAsyncConnection conn;
    
    private async Task Init()
    {
        if (conn != null)
            return;
    
        conn = new SQLiteAsyncConnection(_dbPath);
    
        await conn.CreateTableAsync<Person>();
    }
    

Inserir um item em uma tabela de maneira assíncrona

  1. Modifique a definição do método AddNewPerson para ser async. Altere o tipo de retorno do método para Task.

  2. Adicione a palavra-chave await à chamada de método Init porque Init agora é um método async.

  3. Atualize o método AddNewPerson para inserir um novo Person usando uma operação de inserção assíncrona.

    Seu código deve ficar assim:

    using System.Threading.Tasks;
    ...
    public async Task AddNewPerson(string name)
    {
       int result = 0;
       try
       {
          // Call Init()
          await Init();
    
          // basic validation to ensure a name was entered
          if (string.IsNullOrEmpty(name))
                throw new Exception("Valid name required");
    
          result = await conn.InsertAsync(new Person { Name = name });
    
          StatusMessage = string.Format("{0} record(s) added [Name: {1})", result, name);
       }
       catch (Exception ex)
       {
          StatusMessage = string.Format("Failed to add {0}. Error: {1}", name, ex.Message);
       }
    }
    

Obter todos os itens de uma tabela de maneira assíncrona

  1. Modifique a definição do método GetAllPeople. Esse método deve ser async e retornar um objeto Task<List<Person>>.

  2. Adicione a palavra-chave await à chamada de método Init.

  3. Atualize o método para retornar os resultados usando uma chamada assíncrona.

    Seu código deve ficar assim:

    public async Task<List<Person>> GetAllPeople()
    {
       try
       {
          await Init();
          return await conn.Table<Person>().ToListAsync();
       }
       catch (Exception ex)
       {
          StatusMessage = string.Format("Failed to retrieve data. {0}", ex.Message);
       }
    
       return new List<Person>();
    }
    
  4. Salve o arquivo PersonRepository.cs.

Testar a funcionalidade assíncrona

  1. Expanda MainPage.xaml no Gerenciador de Soluções e abra o arquivo MainPage.xaml.cs.

  2. Modifique ambos os manipuladores de eventos de clicar com o botão para que eles usem os métodos assíncronos da classe PersonRepository. Use as palavras-chave async e await:

      public async void OnNewButtonClicked(object sender, EventArgs args)
      {
         statusMessage.Text = "";
    
         await App.PersonRepo.AddNewPerson(newPerson.Text);
         statusMessage.Text = App.PersonRepo.StatusMessage;
      }
    
      public async void OnGetButtonClicked(object sender, EventArgs args)
      {
         statusMessage.Text = "";
    
         List<Person> people = await App.PersonRepo.GetAllPeople();
         peopleList.ItemsSource = people;
      }
    
  3. Salve o arquivo MainPage.xaml.cs.

  4. Crie e execute o programa no Windows e no Android, verificando se ele ainda funciona como antes.