Como usar o ThreeTenABP no projeto Android

192

Estou fazendo essa pergunta porque sou novo em Java e Android e procurei por horas tentando descobrir isso. A resposta veio de uma combinação de respostas relacionadas, então pensei em documentar o que aprendi para qualquer pessoa que esteja com dificuldades. Ver resposta.

Estou usando o Android Studio 2.1.2 e minha configuração do Java é a seguinte:

>java -version
> openjdk version "1.8.0_91"
> OpenJDK Runtime Environment (build 1.8.0_91-8u91-b14-3ubuntu1~15.10.1-b14)
> OpenJDK 64-Bit Server VM (build 25.91-b14, mixed mode)
Kael
fonte

Respostas:

192

Atenção: Suporte para desugaring da API Java 8+ (Android Gradle Plugin 4.0.0+)

O desenvolvimento desta biblioteca ( ThreeTenABP ) está terminando. Por favor, considere mudar para o plugin Android Gradle 4.0, java.time. *, E seu principal recurso de remoção de biblioteca nos próximos meses.

Para ativar o suporte para essas APIs de idioma em qualquer versão da plataforma Android, atualize o plug-in Android para 4.0.0 (ou superior) e inclua o seguinte no arquivo build.gradle do seu módulo:

android {
  defaultConfig {
    // Required when setting minSdkVersion to 20 or lower
    multiDexEnabled true
  }

  compileOptions {
    // Flag to enable support for the new language APIs
    coreLibraryDesugaringEnabled true
    // Sets Java compatibility to Java 8
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

dependencies {
  coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.5'
}

Primeira descoberta: por que você precisa usar o ThreeTenABP em vez de java.time , ThreeTen-Backport ou até Joda-Time

Esta é uma versão realmente curta do PROCESSO MUITO LONGO de definir um novo padrão. Todos esses pacotes são praticamente a mesma coisa: bibliotecas que fornecem boas e modernas funcionalidades de manipulação de tempo para Java. As diferenças são sutis, mas importantes.

A solução mais óbvia seria usar o java.timepacote interno, pois essa é a nova maneira padrão de lidar com a hora e as datas em Java. É uma implementação do JSR 310 , que era uma nova proposta padrão para manipulação de tempo com base na biblioteca Joda-Time .

No entanto, java.timefoi introduzido no Java 8 . O Android até Marshmallow é executado no Java 7 ("Android N" é a primeira versão a introduzir os recursos da linguagem Java 8). Portanto, a menos que você esteja direcionando apenas para o Android N Nougat e superior, não poderá confiar nos recursos da linguagem Java 8 (não tenho certeza se isso é 100% verdadeiro, mas é assim que entendo). Então java.timeestá fora.

A próxima opção pode ser o Joda-Time , já que o JSR 310 foi baseado no Joda-Time. No entanto, como o leiame do ThreeTenABP indica, por vários motivos, o Joda-Time não é a melhor opção.

A seguir, está o ThreeTen-Backport , que fornece uma porta (mas não toda) da funcionalidade do Java 8 java.timepara o Java 7. Isso é bom para a maioria dos casos de uso, mas, conforme indicado no leia-me do ThreeTenABP , há problemas de desempenho com o Android.

Portanto, a última e aparentemente correta opção é ThreeTenABP .

Segunda descoberta: ferramentas de construção e gerenciamento de dependências

Como a compilação de um programa - especialmente um usando várias bibliotecas externas - é complexa, o Java quase invariavelmente usa uma "ferramenta de construção" para gerenciar o processo. Make , Apache Ant , Apache Maven e Gradle são ferramentas de construção que são usadas com programas Java (consulte esta publicação para comparações). Como observado mais abaixo, Gradle é a ferramenta de compilação escolhida para projetos Android.

Essas ferramentas de construção incluem gerenciamento de dependência. O Apache Maven parece ser o primeiro a incluir um repositório de pacotes centralizado. O Maven introduziu o Maven Central Repository , que permite funcionalidades equivalentes aos php's do composerPackagist e Ruby's do gemrubygems.org. Em outras palavras, o Maven Central Repository é para Maven (e Gradle) o que o Packagist é o compositor - uma fonte definitiva e segura para pacotes com versão.

Terceira descoberta: Gradle lida com dependências em projetos Android

No topo da minha lista de tarefas é ler os documentos da Gradle aqui , incluindo seus e-books gratuitos. Se eu tivesse lido essas semanas atrás, quando comecei a aprender Android, certamente saberia que Gradle pode usar o Repositório Central do Maven para gerenciar dependências em Projetos Android. Além disso, conforme detalhado nesta resposta do StackOverflow, no Android Studio 0.8.9, o Gradle usa o Maven Central Repository implicitamente através do JCenter da Bintray, o que significa que você não precisa fazer nenhuma configuração extra para configurar o repositório - basta listar o dependências.

Quarta descoberta: as dependências do projeto são listadas em [dir do projeto] /app/build.gradle

Mais uma vez, óbvio para quem tem alguma experiência com o Gradle em Java, mas demorei um pouco para descobrir isso. Se você vir pessoas dizendo "Ah, basta adicionar compile 'this-or-that.jar'" ou algo semelhante, saiba que compileé uma diretiva nesse arquivo build.gradle que indica dependências em tempo de compilação. Aqui está a página oficial da Gradle sobre gerenciamento de dependências.

Quinta descoberta: o ThreeTenABP é gerenciado por Jake Wharton, não pelo ThreeTen

Outra questão que eu gastei muito tempo tentando descobrir. Se você procurar o ThreeTen no Maven Central, verá apenas pacotes threetenbp, não threetenabp. Se você for ao repositório do github do ThreeTenABP , verá essa compile 'this-or-that'linha infame na seção Download do Leia-me.

Quando cheguei a este repositório do github, não sabia o que significava essa linha de compilação e tentei executá-la no meu terminal (com uma falha óbvia e previsível). Frustrado, eu não voltei a ele até muito tempo depois que descobri o resto e finalmente percebi que é uma linha Maven Repo apontando para o com.jakewharton.threetenabprepo, em oposição ao org.threetenrepo. Por isso, pensei que o pacote ThreeTenABP não estava no repositório Maven.

Resumo: Fazendo funcionar

Agora tudo parece bem fácil. Você pode obter funções modernas de manipulação de tempo em um projeto Android, certificando-se de que seu [project folder]/app/build.gradlearquivo tenha a implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'linha em sua dependenciesseção:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "me.ahuman.myapp"
        minSdkVersion 11
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}


dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    testImplementation 'junit:junit:4.12'
    implementation 'com.android.support:appcompat-v7:23.4.0'
    implementation 'com.android.support:design:23.4.0'
    implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'
}

Adicione isso também à classe Application:

public class App extends Application {    
    @Override
    public void onCreate() {
        super.onCreate();
        AndroidThreeTen.init(this);
        //...
    }
}
Kael
fonte
1
Obrigado pelo ótimo post. No entanto, gostaria de saber se você considerou o JodaTimeAndroid também.
Bob
@ Bob, não experimentei o JodaTimeAndroid, mas apenas porque não estou realmente trabalhando em nada no momento que exija isso. Pelo que me lembro, a java.timeimplementação foi boa (sendo basicamente uma porta do JodaTime) e tenho certeza de que em mais um ou dois anos, 90% dos usuários estarão no Nougat +, tornando-a uma solução viável para o desenvolvimento.
kael
2
@Bob, o JodaTime é basicamente o mesmo que o JSR-310 (mesmo basicamente feito pelos mesmos caras), exceto que o JSR-310 supostamente tem menos falhas de design (veja este artigo , por exemplo). [... continua abaixo]
M. Prokhorov 28/11
2
Para esclarecer os comentários ... A estrutura java.time ( JSR 310 ) é o sucessor oficial do projeto Joda-Time . Ambos os projetos são liderados pelo mesmo homem, Stephen Colebourne . O projeto Joda-Time agora está no modo de manutenção, com a equipe aconselhando a migração para o java.time.
Basil Bourque
6
Certifique-se de chamar AndroidThreeTen.init(this)antes de usar a API, por exemplo, em onCreate().Veja erro ThreeTen-Backport on Android - ZoneRulesException: arquivos de dados de fuso horário Não registrado .
Ole VV
5

A resposta aceita por kael está correta. Além disso, vou mencionar algumas coisas e fornecer um diagrama sobre como obter a funcionalidade java.time .

java.time embutido no Android 26+

Se você tiver como alvo o Android 26 ou posterior, encontrará uma implementação do JSR 310 ( classes java.time ) incluída no Android. Não é necessário adicionar o ThreeTenABP .

APIs quase idênticas

Apenas para esclarecer, o ThreeTenABP for Android é uma adaptação da biblioteca ThreeTen-Backport que traz a maior parte da funcionalidade java.time para Java 6 e Java 7 . Essa porta traseira compartilha quase uma API idêntica ao java.time .

Suponha que agora você esteja segmentando o Android com mais de 26 anos e use o ThreeTenABP . Posteriormente, você poderá eventualmente descartar o suporte para essas versões anteriores do Android, para usar as classes java.time incluídas no Android. Quando isso acontece, você precisa fazer poucas alterações na sua base de código além de (a) importinstruções de comutação e (b) alterar as chamadas feitas org.threeten.bp.DateTimeUtilspara usar os novos métodos de conversão que foram adicionados às antigas classes de data e hora herdadas ( Date, GregorianCalendar) .

O processo de transição do ThreeTenABP para o java.time deve ser suave e quase indolor.

Quando usar qual estrutura

Aqui está um gráfico mostrando as três estruturas e indicando quando usar qual em quais cenários.

Atualização: O Android Gradle Plugin 4.0.0+ traz uma nova 4ª opção, a API desugaring, para disponibilizar um subconjunto da funcionalidade java.time não incorporada originalmente no Android anterior. Veja o topo da resposta principal de kael.

Tabela de qual biblioteca java.time a ser usada com qual versão do Java ou Android


Sobre java.time

A estrutura java.time é integrada ao Java 8 e posterior. Essas classes suplantar os velhos problemáticos legados aulas de data e hora, como java.util.Date, Calendar, e SimpleDateFormat.

Para saber mais, consulte o Tutorial do Oracle . E procure Stack Overflow para muitos exemplos e explicações. A especificação é JSR 310 .

O projeto Joda-Time , agora em modo de manutenção , aconselha a migração para as classes java.time .

Você pode trocar objetos java.time diretamente com seu banco de dados. Use um driver JDBC compatível com JDBC 4.2 ou posterior. Não há necessidade de strings, não há necessidade de java.sql.*classes. O Hibernate 5 e o JPA 2.2 suportam java.time .

Onde obter as classes java.time?

Basil Bourque
fonte
4

Adicione o seguinte no seu arquivo de compilação no Android Studio.

implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'

Crie a classe Application e inicialize-a assim:

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        AndroidThreeTen.init(this)
    }
}
Richard Kamere
fonte