Tengo un proyecto basado en monedas y modernización en la arquitectura MVVM. Quiero imprimir los datos con 'ViewModel' y agregar el valor de 'token' al encabezado en tiempo de ejecución después de registrar este proyecto. Pero no pude proporcionar la estructura de contexto necesaria para obtener el token que salvé en SharedPreferences. ¿Cómo puedo manejar esto en su forma más limpia?

 fun createNetworkClient(baseUrl: String) =
        retrofitClient(baseUrl, httpClient())


    private fun httpClient(): OkHttpClient {

        val httpLoggingInterceptor = HttpLoggingInterceptor(HttpLoggingInterceptor.Logger.DEFAULT)
        val clientBuilder = OkHttpClient.Builder()
        if (BuildConfig.DEBUG) {
            httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
            clientBuilder.addInterceptor(httpLoggingInterceptor)
        }
        clientBuilder.addInterceptor { chain ->
            val newRequest = chain.request().newBuilder()
                .addHeader( //I can't get token because there is no context here.
                    "Authorization", "Bearer ${PreferencesHelper.getInstance(context).token.toString()}"
                )
                .build()
            chain.proceed(newRequest)
        }



        clientBuilder.readTimeout(120, TimeUnit.SECONDS)
        clientBuilder.writeTimeout(120, TimeUnit.SECONDS)
        return clientBuilder.build()
    }

    private fun retrofitClient(baseUrl: String, httpClient: OkHttpClient): Retrofit =
        Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(httpClient)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()

AppModule

val appModule = module {
    single {
        androidApplication().getSharedPreferences("PREFERENCES", android.content.Context.MODE_PRIVATE)
    }
    single { createNetworkClient(BuildConfig.BASE_URL) }
    single { (get() as Retrofit).create(Api::class.java) } 
    viewModel {
        ContactViewModel(get())
    }
}

MyContactActivity

 private val contactList: ContactViewModel  by viewModel()
    override fun onCreate(savedInstanceState: Bundle?) {
        viewModel = contactList

        super.onCreate(savedInstanceState)
        binding.adapter = ContactAdapter(this)
        binding.layoutManager = LinearLayoutManager(this)

        contactList.getContactList()

        contactList.contactListLiveData.observe(this, Observer { list ->
            if (list != null)
                binding.adapter?.update(list)
        })
    }
2
Hasan Kucuk 28 jun. 2019 a las 17:25

1 respuesta

La mejor respuesta

Puede crear un módulo de koin para proporcionar las preferencias compartidas:

val sharedPreferencesModule = module {

   single {
      androidApplication().getSharedPreferences("PREFERENCES",  android.content.Context.MODE_PRIVATE)
   }
}

Y luego inyecte con Koin en la clase que genera el cliente de retrofit.

EDITAR

Necesitas modificar su firma de método createNetworkClient:

fun createNetworkClient(baseUrl: String, preferences: SharedPreferences)

Y luego inyecarlo con koin:

val appModule = module {
    single {
        androidApplication().getSharedPreferences("PREFERENCES", android.content.Context.MODE_PRIVATE)
    }
    single { createNetworkClient(BuildConfig.BASE_URL, get()) }

    ...
}

Luego, recibirá las preferencias compartidas inyectadas en el método createNetworkClient y solo necesitará implementar la lógica para recuperar el token de las preferencias compartidas.

1
Jaime Suarez 28 jun. 2019 a las 14:55