Skip to content

AleBarreto/Android-EX

Repository files navigation

Android-EX

Projeto desenvolvido com o intuito de ajudar na criação/setup de novos projetos Android modularizado, diminuindo consideravelmente o tempo de configuração do gradle e buildSrc.

obs: Cada modulo segue o conceito do clean arch baseado na divisão de camadas [data, domain, presentation, ...], porém todo o projeto foi modularizado pensando em novas features e cada feature possue suas camadas.

Principais Tecnologias/Frameworks

  • Flow
  • Hilt
  • ViewBinding
  • Gradle Kts
  • AndroidX
  • MockK
  • Koin (Toda configuração está em uma branch especifica, criada por @jotavier )

Navegação entre modulos

o modulo de navigation foi criado para conter todos os contratos de navegação entre os modulos, exemplo:

// :navigation file: FeatureBNavigation.kt
interface FeatureBNavigation {
    fun navigationToFeatureB(context: Context, idMovie: Long)
}

e cada modulo deve prover a implementação do contrato e fornecer na arvore de dependencia, assim ensinando como ser chamado.

// :featureB file: FeatureBNavigationImpl.kt
const val EXTRA_ID_MOVIE = "id_movie"
internal class FeatureBNavigationImpl @Inject constructor() : FeatureBNavigation {
    override fun navigationToFeatureB(context: Context, idMovie: Long) {
        val intent = Intent(context, FeatureBActivity::class.java)
        intent.putExtra(EXTRA_ID_MOVIE, idMovie)
        context.startActivity(intent)
    }
}

fornecendo para injeção de dependencia com Hilt

// :featureB file: NavigationModule.kt
@Module
@InstallIn(SingletonComponent::class)
internal abstract class NavigationModule {
    @Binds
    abstract fun bindNavigation(
        featureBNavigationImpl: FeatureBNavigationImpl
    ): FeatureBNavigation
}

como chamar a activity do moduloB no moduloA:

// :featureA file: FeatureAActivity.kt
@Inject
lateinit var navigation: FeatureBNavigation

navigation.navigationToFeatureB(this, idMovie = id)

navigation

features

Network

Foi criado o modulo de network para prover toda a configuração do retrofit e seus interceptors:

// :network file: NetworkModule.kt
 @Provides
    fun providesHttpLoggingInterceptor() = HttpLoggingInterceptor()
        .apply {level = if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY elseHttpLoggingInterceptor.Level.NONE}
        
    @Provides
    fun providesDefaultInterceptorQueryParameter() = DefaultQueryParameterInterceptor()
    
    @Provides
    fun providesOkHttpClient(
        httpLoggingInterceptor: HttpLoggingInterceptor,defaultInterceptorQueryParameter: DefaultQueryParameterInterceptor
    ): OkHttpClient =
        OkHttpClient
            .Builder()
            .addInterceptor(httpLoggingInterceptor)
            .addInterceptor(defaultInterceptorQueryParameter)
            .build()

    @Singleton
    @Provides
    fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit = Retrofit.Builder()
        .addConverterFactory(GsonConverterFactory.create())
        .baseUrl(BuildConfig.BASE_URL_TMDB)
        .client(okHttpClient)
        .build()

Cada modulo de feature deve forncener somente a interface do serviço e solicitar da injeção de dependencia o retrofit provido pelo modulo de network

// :featureA file: FeatureAService.kt
internal interface FeatureAService {
    @GET("movie/popular")
    suspend fun getPopularMovies(@Query("language") language: String = "pt-BR"): MovieResultResponse
}
// :featureA file: FeatureServiceAModule.kt
@Module
@InstallIn(ViewModelComponent::class)
internal object ServiceAModule {

    @Provides
    fun provideFeatureAService(retrofit: Retrofit): FeatureAService =
        retrofit.create(FeatureAService::class.java)
}

O codigo acima cria uma implementação dos endpoints da API definidos pela interface de serviço. Como usar a interface da api:

// :featureA file: RemoteMovieDataSource.kt
internal class RemoteMovieDataSource @Inject constructor(private val service: FeatureAService) {
    fun getPopularMovies(): Flow<MovieResultResponse> = flow {emit(service.getPopularMovies())}
}

navigation

Camadas do modulo feature

Cada modulo feature segue o conceito do clean arch baseado na divisão de camadas, porém todo o projeto foi modularizado pensando em novas features e cada feature pode possuir camadas a mais baseado em sua necessidade.

  • Data - responsavel por prover os conteudos e request da API.
  • DI - responsavel pela injeção de dependencia do modulo.
  • Domain - regras de negocios se houver.
  • Navigation - prover navegação para dentro do modulo.
  • Presentation - toda camada de view e viewModels.

camadas

Commons

O modulo commons deve ter a responsabilidade de conter tudo que for comun entre os modulos, exemplo: ExtensionFunctions e tambem injeçoes de depencias comum entre os modulos como os Dispatchers.

commons

BuildSrc

TODO

Arquivo secrets.properties.gpg

TODO

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages