Vortex

Additional

Language
Kotlin
Version
N/A
Created
May 10, 2019
Updated
Jul 6, 2019
Owner
Yazan Tarifi (Yazan98)
Contributor
Yazan Tarifi (Yazan98)
1
Activity
Badge
Generate
Download
Source code

Blurb

Vortex

In a lot of the time you download a lot of libraries to build your application and this process is cumbersome and there is no fixed infrastructure to build your application here vortex simply will build everything at your application With Specific Structure and this structure support Viper and MVVM Architecture based on RxJava 2 ... this library works with Clean Architecture With 4 Layers (Container , Data , Logic , Domain)

Application Layers :

  1. Container (UI Layer) : This Layer Have All Views At The Application Such As (Activity , Fragment , Dialog , Widget , Notifications , RecyclerView Adapters , UI Actions For Navigators (Vortex Routers))

  2. Data Layer : This Layer Have All Api Requests For Endpoint and Local Database

  3. Logic : This Layer Have All Implementation Views With Logic For Every Feature Viper : Presenter For Each View to handle Everything at this view Mvvm : ViewModel For Each View to save and handle the data and this implementation is Connected With View Lifecycle WIth LiveCycle From Android Architecture Components

  4. Domain Layer : This Layer Have All Use Cases For The Application (Interactors) : At every interactor you should execute the bussness logic at every request and then execute the request to end point ... also this layer have all models at application (You Can Build This Layer With Android Implementation Or Pure Java Implementation With Config The Module With Java Or Android Plugin And Select Your Thread Provider From Vortex Implementation Like The Example)

Application Basic Flow

Maven Central Packages : https://mvnrepository.com/artifact/com.yazan98.vortex

Setup Repositories

Add Sonatype's snapshots repository:

 repositories {
    mavenCentral()
    maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
    maven { url  "https://dl.bintray.com/yt98/Vortex"}
  }

Setup Gradle Packages

    // Setup Vortex With Viper Architecture
    dependencies {
        implementation "io.reactivex.rxjava2:rxjava:2.2.10"
        
        // Container Layer
        implementation "com.yazan98.vortex:vortex-viper-ktx:{final-version}"
        implementation "com.yazan98.vortex:vortex-router-ktx:{final-version}"
        implementation "com.yazan98.vortex:vortex-extras-ktx:{final-version}"
        
        // Domain Layer
        implementation "com.yazan98.vortex:vortex-core-ktx:{final-version}"
        
        // Data Layer
        implementation "com.yazan98.vortex:vortex-data-ktx:{final-version}"
        
        // Logic Layer
        implementation "com.yazan98.vortex:vortex-viper-ktx:{final-version}"
        
    }
    
    // Setup Vortex With MVVM Architecture
    dependencies {
        implementation "io.reactivex.rxjava2:rxjava:2.2.10"
        
        // Container Layer
        implementation "com.yazan98.vortex:vortex-vm-ktx:{final-version}"
        implementation "com.yazan98.vortex:vortex-router-ktx:{final-version}"
        implementation "com.yazan98.vortex:vortex-extras-ktx:{final-version}"
        
        // Domain Layer
        implementation "com.yazan98.vortex:vortex-core-ktx:{final-version}"
        
        // Data Layer
        implementation "com.yazan98.vortex:vortex-data-ktx:{final-version}"
        
        // Logic Layer
        implementation "com.yazan98.vortex:vortex-vm-core-ktx:{final-version}"
        
    }

Usage

  1. Application Class :
class VortexApp : VortexMultiApplication() , Thread.UncaughtExceptionHandler {
   

   override fun onCreate() {
       super.onCreate()
       Vortex.registerCompatVector()
           .registerArchitecture(VortexArchitecture.VIEW_MODEL)
           .registerApplicationLogger(VortexLogger.TIMBER , BuildConfig.DEBUG)
           .registerExceptionHandler(this)
           .registerFirebase(this)
           .registerImageLoader(ImageLoaders.FRESCO , this)
           .registerImageLoader(ImageLoaders.PICASSO , this)
           .registerStrictMode(BuildConfig.DEBUG)
           .registerCrashLytics(this , BuildConfig.DEBUG)
           .startLeakCanary(BuildConfig.DEBUG)
           .registerOfflineCachingFirebaseDatabase(this)
           .registerStetho(this)
           .build()
   }

   override fun uncaughtException(t: Thread?, e: Throwable?) {
       // Show Dialog With uncaught Exceptions 
   }
}
  1. Interactor:
class GithubInteractor : VortexSingleInteractor<GithubUser, GithubInteractor.GithubInteractorParams>() {

   @Throws(VortexInvalidException::class)
   override fun validate(content: GithubInteractorParams) {
       if (content.githubName.isEmpty()) {
           throw VortexInvalidException("Github Name Missing")
       }
   }

   override fun execute(request: Single<GithubUser>): Disposable {
       return RxSingleProvider<GithubUser>(VortexAndroidThreadProvider())
           .getSingleRequest(request)
           .subscribe(
               {
                   subscriber.onSuccess(it)
               },
               {
                   subscriber.onError(it)
               }
           )
   }

   data class GithubInteractorParams(
       var githubName: String
   )
}
  1. ViewModel :
class GithubViewModel : VortexNetworkViewModel<GithubView>() {

   val data: MutableLiveData<GithubUser> by lazy { MutableLiveData<GithubUser>() }
   private val interactor: GithubInteractor by lazy { GithubInteractor() }
   private val repo: GithubRepository by lazy { GithubRepository() }

   init {
       acceptNewState(State.INIT)
       interactor.subscriber = object : VortexSingleSubscriber<GithubUser>() {
           override fun onSuccess(t: GithubUser) {
               getView().onSuccess(t)
               data.postValue(t)
               acceptNewState(State.FINISHED)
           }

           override fun onError(e: Throwable) {
               getView().showError(e.message!!)
               acceptNewState(State.EMPTY_RESULT)
           }
       }
   }

   fun getUserByName(username: String) {
       try {
           interactor.validate(GithubInteractor.GithubInteractorParams(username))
           acceptNewState(State.LOADING)
           repository.addRequest(interactor.execute(repo.getService().getUserByName()))
       } catch (ex: VortexInvalidException) {
           getView().showError(ex.message)
           acceptNewState(State.EMPTY_RESULT)
       }

   }

   override fun destroy() {
       super.destroy()
       repository.clearAllRequests()
   }
}
  1. Fragment :
class GithubFragment : VortexNetworkFragment<GithubView, GithubViewModel>(), GithubView {

   private var githubViewModel: GithubViewModel? = null

   override fun getViewModel(): GithubViewModel {
       return ViewModelProviders.of(this).get(GithubViewModel::class.java)
   }

   override fun getLayoutRes(): Int {
       return R.layout.fragment_github
   }

   override fun initScreen() {
       githubViewModel = getViewModel()
       githubViewModel!!.attachView(this)

       githubViewModel!!.data.observe(this, Observer { onSuccess(it) })
       if (githubViewModel!!.data.value == null) {
           githubViewModel!!.getUserByName("Yazan98")
       }
   }

   override fun showError(error: String) {
       Toast.makeText(activity!!, error, Toast.LENGTH_SHORT).show()
   }

   override fun onNewState(newState: State) {
       when (newState) {
           State.EMPTY_RESULT -> hideLoading()
           State.LOADING -> showLoading()
           State.FINISHED -> hideLoading()
       }
   }

   override fun onSuccess(data: GithubUser) {
       // Fill Data In UI
   }

   override fun showLoading() {
       // Show Progress Bar
   }

   override fun hideLoading() {
       // hide progress bar
   }

   override fun onDestroy() {
       super.onDestroy()
       this.githubViewModel!!.destroy()
       this.githubViewModel = null
   }

   override fun onDetach() {
       super.onDetach()
       this.githubViewModel!!.destroy()
       this.githubViewModel = null
   }
   
}

Data Repository

class GithubRepository : VortexRepository<GithubApi>() {
    
    init {
        // If You Want To Provide Custom Headers You Can Change This Line
        retrofit = RetrofitProvider.getDefaultRetrofit(getBaseUrl())
    }

    override fun getBaseUrl(): String {
        return ""
    }

    public override fun getService(): GithubApi {
        return getServiceProvider().create(GithubApi::class.java)
    }

}

Extras

The Container Layer (UI) Have Common And Utils For Common Cases Check The Extras Extension To implement them

Android Application Example Build With Github Api

Android Application With (Mvvm) https://github.com/Yazan98/Vortex-Sample

Road Map

  1. Annotation processor Validator For Interactors
  2. Room Implementation With RxJava For Databases
  3. Common Screens Like Permissions , Players , Maps

License

     Copyright (C) 2019 Yazan Tarifi
     Licensed under the Apache License, Version 2.0