top of page
Rechercher
Photo du rédacteurRuben Mim

Kotlinx Serialization Library




" In computing, serialization (US spelling) or serialisation (UK spelling) is the process of translating a data structure or object state into a format that can be stored (for example, in a file or memory data buffer) or transmitted (for example, across a computer network) and reconstructed later (possibly in a different computer environment). "


Two days ago the JetBrain team published a new post about serializing stuff in Kotlin

Was I intrigued ?




Of course ! and I wanted to show you a very little use of the the deserializing process while using Rx and URL from java.net.URL ( lazyness guys, lazyness). JSONs have never been easier to be parsed !





First all of implementation :


apply plugin: 'kotlinx-serialization'
apply plugin: "org.jetbrains.kotlin.plugin.serialization"

...


  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

kotlinOptions {
    jvmTarget = "1.8"
}

...

dependencies{

implementation "io.reactivex.rxjava3:rxkotlin:3.0.0"
implementation "io.reactivex.rxjava3:rxandroid:3.0.0"

implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.0")

implementation 'androidx.recyclerview:recyclerview:1.1.0'

}

Permission to use internet in the manifest please :


    <uses-permissionandroid:name="android.permission.INTERNET"/>




Once it's done, create a ViewModel and set it up like this :


class VM : ViewModel(){

var listOfRepo = MutableLiveData<List<Repo>>()

private val disposable = CompositeDisposable()
/**
* Asynchronous work to prevent us from blocking the UI while fetching and transforming the data.     
* Here we update the MutableLiveData listOfRepo     
*     
* For learning and debugging purpose we use the fancy method subscribeBy()
*/
fun fetchListOfData(){
val observable = getStringObservable()        
observable            
.subscribeOn(Schedulers.io())            .observeOn(AndroidSchedulers.mainThread())            
.subscribeBy(                
onNext = {result ->listOfRepo.value =  result },                
onError = 
{error->Log.e("VM", "fetchListOfData :${error.localizedMessage}")}            )
.addTo(disposable)    
}


/**     
* Returns an Observable like below :     
* URl => String => List<Repo> wrapped into an Observable
*/

private fun getStringObservable() :Observable<List<Repo>> {
return Observable.create { 
emitter ->
emitter.onNext(
Json{ ignoreUnknownKeys = true}
.decodeFromString( URL(MainActivity.URL).readText())
            )        
    }   
  }
  
  /**     
  * When the view model is destroyed we get rid of all observables
  */
  override fun onCleared() {
  super.onCleared()
  disposable.clear()
  }
      
      
      
}



Don't forget to create an object to Serialized to the serialized the result to and to be used by the adapter .


@Serializable()
dataclass Repo ( val name : String?, val description :String?)





Return to you main activity and :

class MainActivity : AppCompatActivity() { 

private var viewModel :VM?  = null 
private var adapter  :AdapterRepo? = null 

companion object {
          const val URL=
           "https://api.github.com/repositories?since=364"
    }
    /**
     *     
     * UI update
     */
     override fun onCreate ( savedInstanceState : Bundle? ) 
     {           
     
     super.onCreate(savedInstanceState)          
     setContentView(R.layout.activity_main)        
     
     viewModel = ViewModelProvider.AndroidViewModelFactory             
     .getInstance( this.application )
     .create(VM::class.java)
     
    adapter = AdapterRepo(this)
    recycler.layoutManager = LinearLayoutManager(this)        
    
    viewModel?.listOfRepo?.observe(this, { list ->            
    adapter?.update(list)
    recycler.adapter = adapter
            })        
      
      viewModel?.fetchListOfData()    
    }
      
      
 }

        
 //Item for RecyclerView setup
             
class AdapterRepo ( private val context :Context) :        RecyclerView.Adapter<AdapterRepo.VH>(){
       
private var listOfRepo  = listOf<Repo>()
       
class VH (itemView :View)  : RecyclerView.ViewHolder( itemView ){

       var title  : TextView?  =null 
       var description :TextView? =null 
       
       init {
            title =  itemView.findViewById(R.id.title)            
            description =  itemView.findViewById(R.id.description)     
             }
             
       fun bind( titleValue :String? ,  descriptionValue :String?){            
          title?.text =  titleValue
          description?.text =  descriptionValue  
           }    
 } 
         
       fun update (list:List<Repo>){
       listOfRepo = list      
       notifyDataSetChanged()  
       }
                   
                   
       override fun onCreateViewHolder(parent: ViewGroup, viewType:             Int): VH { 
       
       val v = LayoutInflater.from(context)
       .inflate(R.layout.repo_item,parent,false)
      
       return VH(v)    
       
        }
        
        
        override fun onBindViewHolder( holder : VH, position : Int) {
        
         val repo =  listOfRepo[position]
         holder.bind(repo.name, repo.description)    
         
         }
          override fun getItemCount(): Int = listOfRepo.size
                    
                    
}


Some tips you should know :




- If you forget to apply the plugins at the top of your gradle file @Serializable in the data class will be highlighted and the serialization will fail.


-If by any chance you'd like to change the setup and the use know that URL(MainActivity.URL).readText() has to be called asynchronously !


- If you want to use Retrofit coupled with Kotlin.serialization implement :

implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0")

And in your API builder set it up as your converter.


- For best pratice matter and data usage, you should store the result into a file, just saying.


- { IgnoreUnknownKeys = true } tells the library, the object you want to create clearly doesn't need all the properties , therefore you tell it to ignore the one you don't want.





Link to the project :



139 vues0 commentaire

Posts récents

Voir tout

Comments


bottom of page