using Retrofit enqueue calls getting problem - android

getting this error for enqueue for kotlin android and it is showing Unresolved reference: enqueue
my code
class NewsActivity : AppCompatActivity() {
private lateinit var mRecyclerView: RecyclerView
private lateinit var mProgressBar: ProgressBar
private lateinit var mAdapter: NewsAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_news)
mRecyclerView = findViewById(R.id.recycler_view)
mProgressBar = findViewById(R.id.progress_circular)
getItemList()
}
private fun getItemList() {
mProgressBar.visibility = View.VISIBLE
val apical = ApiClient.create().getData()
apical.enqueue(object : retrofit2.Callback<List<DataModelItem>> {
override fun onFailure(call: Call<List<DataModelItem>>, t: Throwable) {
mProgressBar.visibility = View.GONE
}
override fun onResponse(
call: Call<List<DataModelItem>>,
response: Response<List<DataModelItem>>) {
if (response.isSuccessful){
val itemListNews = response.body()!!
mAdapter = NewsAdapter(itemListNews)
val layoutManager = LinearLayoutManager(this#NewsActivity)
mRecyclerView.layoutManager = layoutManager
mRecyclerView.adapter = mAdapter
}
}
})
}
}
this is News activity
class NewsAdapter(private val itemList : List<DataModelItem>) : RecyclerView.Adapter<NewsAdapter.CustomViewHolder>() {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): NewsAdapter.CustomViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_view, parent, false)
return CustomViewHolder(view)
}
override fun getItemCount(): Int {
return itemList.size
}
override fun onBindViewHolder(holder: NewsAdapter.CustomViewHolder, position: Int) {
val itemData = itemList.get(position)
Picasso.get().load(itemData.images).into(holder.img1)
holder.Titlenews.setText(itemData.title)
holder.txt_description.setText(itemData.summary)
holder.publish_time.setText(itemData.publish_date)
}
inner class CustomViewHolder(view: View): RecyclerView.ViewHolder(view){
var img1:ImageView
var Titlenews: TextView
var txt_description: TextView
var publish_time: TextView
init {
img1 = view.findViewById(R.id.item_image)
Titlenews = view.findViewById(R.id.Titlenews)
txt_description = view.findViewById(R.id.txt_description)
publish_time = view.findViewById(R.id.publish_time)
}
}
}
this is the news adapter
object ApiClient {
var BASE_URL = ""
fun create() :Api{
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build()
return retrofit.create(Api::class.java)
}
}
this is Api client
Help required
I want not getting a solution as always it is giving me an error for enqueue .

Try changing
apical.enqueue(object : retrofit2.Callback<List<DataModelItem>> {
to
apical.enqueue(object : retrofit.Callback<List<DataModelItem>> {

Related

cant call GItHub search user API with Retrofit

im trying to make an apps that use GitHub search user API with Retrofit.i want to make that when i type some username,it will show any github username related with it will be displayed on RecyclerView.is there something that i've missed or write wrongly?
since the apps run just fine,but when i try to search the username,it just show the 1 username type instead every username related to it.
here's my example to search username:
https://api.github.com/search/users?q=sidiqpermana
and heres some of my coding
RetrofitClient.kt
object RetrofitClient {
private const val BASE_URL = "https://api.github.com/"
private val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
val apiInstance = retrofit.create(Api::class.java)
}
Api.kt
interface Api {
#GET("search/users")
#Headers("Authorization: token N7QNdhhICaLmxSTzAWr70V7nqf6yaK4B6Z15")
fun getSearchUsers(
#Query("q") query: String
):Call<UserResponse>
}
UserResponse.kt
data class UserResponse(
val items : ArrayList<User>
)
UserAdapter.kt
class UserAdapter : RecyclerView.Adapter<UserAdapter.UserViewHolder>() {
private val list = ArrayList<User>()
fun setList(users: ArrayList<User>){
list.clear()
list.addAll(users)
notifyDataSetChanged()
}
inner class UserViewHolder(val binding: ItemUserBinding) : RecyclerView.ViewHolder(binding.root){
fun bind(user: User){
binding.apply {
Glide.with(itemView)
.load(user.avatar_url)
.transition(DrawableTransitionOptions.withCrossFade())
.centerCrop()
.into(tvUser)
tvUsername.text = user.login
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
val view = ItemUserBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return UserViewHolder((view))
}
override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
holder.bind(list[position])
}
override fun getItemCount(): Int = list.size
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel: MainViewModel
private lateinit var adapter: UserAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
adapter = UserAdapter()
adapter.notifyDataSetChanged()
viewModel= ViewModelProvider(this, ViewModelProvider.NewInstanceFactory()).get(MainViewModel::class.java)
binding.apply {
rvUser.layoutManager = LinearLayoutManager ( this#MainActivity)
rvUser.setHasFixedSize(true)
rvUser.adapter = adapter
btnSearch.setOnClickListener{
searchUser()
}
etQuery.setOnKeyListener { _, KeyCode, event ->
if (event.action == KeyEvent.ACTION_DOWN && KeyCode == KeyEvent.KEYCODE_ENTER){
searchUser()
return#setOnKeyListener true
}
return#setOnKeyListener false
}
}
viewModel.getSearchUsers().observe(this,{
if (it!=null){
adapter.setList(it)
showLoading(false)
}
})
}
private fun searchUser(){
binding.apply {
val query = etQuery.text.toString()
if (query.isEmpty()) return
showLoading(true)
viewModel.setSearchUsers(query)
}
}
private fun showLoading(state: Boolean){
if (state){
binding.progressBar.visibility = View.VISIBLE
}else{
binding.progressBar.visibility = View.GONE
}
}
}
MainViewModel.kt
class MainViewModel : ViewModel() {
val listUsers = MutableLiveData<ArrayList<User>>()
fun setSearchUsers(query: String){
RetrofitClient.apiInstance
.getSearchUsers(query)
.enqueue(object : Callback<UserResponse>{
override fun onResponse(
call: Call<UserResponse>,
response: Response<UserResponse>
) {
if (response.isSuccessful){
listUsers.postValue(response.body()?.items)
}
}
override fun onFailure(call: Call<UserResponse>, t: Throwable) {
t.message?.let { Log.d("Failure", it) }
}
})
}
fun getSearchUsers(): LiveData<ArrayList<User>>{
return listUsers
}
}

kotlin error recycler view with gridlayout type was mismatched

im facing errors in recyclerView here is //
data class categories(
val Name: String,
val Image:Int
)
here is model /////
object CategoriesModel {
fun getImages(): ArrayList<categories> {
val ImagesList = ArrayList<categories>()
val categoryFirst = categories(
"Memmals",R.drawable.memmals
)
ImagesList.add(categoryFirst)
val categorySecond = categories(
"Memmals",R.drawable.fish
)
ImagesList.add(categorySecond)
return ImagesList
}
}
//// adapter///
class CategoriesAdapter(private val itemList: ArrayList) :
RecyclerView.Adapter<CategoriesAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CategoriesAdapter.ViewHolder {
val view =LayoutInflater.from(parent.context)
.inflate(R.layout.memmals, parent,false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: CategoriesAdapter.ViewHolder, position: Int) {
holder.bind(categories("Memmals",2))
}
override fun getItemCount(): Int {
return itemList.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(category: categories) {
val textViewName = itemView.findViewById<TextView>(R.id.txtCategory)
textViewName.text = category.Name
val txtImage=itemView.findViewById<View>(R.id.image)
txtImage.id=category.Image
}
}
}
/////main activity///
class MainActivity : AppCompatActivity() {
private lateinit var mAdapter: CategoriesAdapter
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
binding= ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.recyclerView.setOnClickListener{
val intent=Intent(this,Level1::class.java)
startActivity(intent)
}
val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
recyclerView.layoutManager = GridLayoutManager(this,2)
val itemList = ArrayList<CategoriesModel>()
// from here
itemList.add(categories("Memmals",R.drawable.memmals))
itemList.add(categories("Fishes",R.drawable.fish))
itemList.add(categories("Arthropods",R.drawable.dear))
itemList.add(categories("Yalk",R.drawable.yalk))
//to here errors are there
//Adapter setting
mAdapter = CategoriesAdapter(itemList)
recyclerView.adapter = mAdapter
}
}
/// here is the error///
MainActivity.kt: (34, 22): Type mismatch: inferred type is categories but CategoriesModel was expected
MainActivity.kt
val itemList = ArrayList<CategoriesModel>()
should be changed to
val itemList = ArrayList<categories>()
because you are using CategoriesModel object and expected is categories.

I am facing an error "No adapter attached; skipping layout"

I am new in kotlin and retrofit, when I run this app it shows nothing in my device. But I check the logcat and found this errorNo adapter attached; skipping layout.Sometimes ago I post this question, some people answer this but this answer not correct
CountryActivity.kt
var recyclerView: RecyclerView = findViewById(R.id.countryRecyclerView)
recyclerView.layoutManager = LinearLayoutManager(this)
var apiInterface: CountryDataInterface =
CountryApiClient.getApiClient()!!.create(CountryDataInterface::class.java)
apiInterface.getCountryData().enqueue(object : Callback<List<Country>> {
override fun onFailure(call: Call<List<Country>>, t: Throwable) {}
override fun onResponse(call: Call<List<Country>>, response: Response<List<Country>>) {
val countryData = response.body()!!
recyclerView.adapter = CountryDataAdapter(countryData)
CountryDataAdapter.kt
class CountryDataAdapter(var countryDataList: List<Country>?):
RecyclerView.Adapter<CountryDataAdapter.RecyclerViewHolder>() {
class RecyclerViewHolder(itemView: View):RecyclerView.ViewHolder(itemView) {
var countryName: TextView = itemView.findViewById(R.id.countryName)
var casesTotal: TextView = itemView.findViewById(R.id.casesTotal)
var casesToday: TextView = itemView.findViewById(R.id.casesToday)
var deathTotal: TextView = itemView.findViewById(R.id.deathTotal)
var deathToday: TextView = itemView.findViewById(R.id.deathToday)
var recoveredAll: TextView = itemView.findViewById(R.id.recoveredAll)
var activeAll: TextView = itemView.findViewById(R.id.activeAll)
var criticalAll: TextView = itemView.findViewById(R.id.criticalAll)
fun bindData(countryDataList: List<Country>?, position: Int){
countryName.text = countryDataList!!.get(position).countryName.toString()
casesTotal.text = countryDataList!!.get(position).cases.toString()
casesToday.text = countryDataList!!.get(position).todayCases.toString()
deathTotal.text = countryDataList!!.get(position).deathTotal.toString()
deathToday.text = countryDataList!!.get(position).deathToday.toString()
recoveredAll.text = countryDataList!!.get(position).recovered.toString()
activeAll.text = countryDataList!!.get(position).activePatient.toString()
criticalAll.text = countryDataList!!.get(position).critical.toString()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerViewHolder {
var view: View = LayoutInflater.from(parent!!.context).inflate(R.layout.country_row,parent,false)
return RecyclerViewHolder(view)
}
override fun getItemCount(): Int {
return countryDataList!!.size
}
override fun onBindViewHolder(holder: RecyclerViewHolder, position: Int) {
holder.bindData(countryDataList,position)
}
}
I think your issue is because you're calling recyclerView.adapter = CountryDataAdapter(countryData) in your Async function.
From what your post shows
override fun onResponse(call: Call<List<Country>>, response: Response<List<Country>>) {
val countryData = response.body()!!
recyclerView.adapter = CountryDataAdapter(countryData)
recyclerView.adapter = CountryDataAdapter(countryData) is in onResponse which is async, when your activity lunch, your adapter isn't set as it waits the result from the network to set it.
It would be better to set it to:
At the beginning of your activity add var countryData: List<Country> = ArrayList()
EDIT after checking Repo:
You get nothing because your call is getting into onFailure. You should add log to see this kind of things.
CountryActivity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_country)
val recyclerView: RecyclerView = findViewById(R.id.cRecyclerView)
var countryData: List<Country> = ArrayList()
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.setHasFixedSize(true)
recyclerView.adapter = CountryDataAdapter(countryData)
// recyclerView.addItemDecoration(DividerItemDecoration(this, DividerItemDecoration.VERTICAL))
val apiInterface: CountryDataInterface = CountryApiClient.getApiClient()!!.create(CountryDataInterface::class.java)
apiInterface.getCountryData().enqueue(object : Callback<List<Country>> {
override fun onFailure(call: Call<List<Country>>, t: Throwable) {
val data = Country(1, 2,3,4,5,6,7,8)
countryData = listOf(data)
recyclerView.adapter = CountryDataAdapter(countryData)
Log.d("onFailure", "ERROR")
}
override fun onResponse(call: Call<List<Country>>, response: Response<List<Country>>) {
if (response.isSuccessful) {
countryData = response.body()!!
recyclerView.adapter = CountryDataAdapter(countryData)
}
}
})
}
Adapter:
class CountryDataAdapter(private var countryDataList: List<Country>):
RecyclerView.Adapter<CountryDataAdapter.RecyclerViewHolder>() {
class RecyclerViewHolder(itemView: View):RecyclerView.ViewHolder(itemView) {
val countryName: TextView = itemView.findViewById(R.id.countryName)
val casesTotal: TextView = itemView.findViewById(R.id.casesTotal)
val casesToday: TextView = itemView.findViewById(R.id.casesToday)
val deathTotal: TextView = itemView.findViewById(R.id.deathTotal)
val deathToday: TextView = itemView.findViewById(R.id.deathToday)
val recoveredAll: TextView = itemView.findViewById(R.id.recoveredAll)
val activeAll: TextView = itemView.findViewById(R.id.activeAll)
val criticalAll: TextView = itemView.findViewById(R.id.criticalAll)
fun bindData(countryDataList: List<Country>, position: Int){
val item = countryDataList[position]
countryName.text = item.countryName.toString()
casesTotal.text = item.cases.toString()
casesToday.text = item.todayCases.toString()
deathTotal.text = item.deathTotal.toString()
deathToday.text = item.deathToday.toString()
recoveredAll.text = item.recovered.toString()
activeAll.text = item.activePatient.toString()
criticalAll.text = item.critical.toString()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerViewHolder {
val view: View = LayoutInflater.from(parent.context).inflate(R.layout.country_row,parent,false)
return RecyclerViewHolder(view)
}
override fun getItemCount(): Int {
return countryDataList.size
}
override fun onBindViewHolder(holder: RecyclerViewHolder, position: Int) {
holder.bindData(countryDataList,position)
}
}

Data won't display when RecyclerView with ListAdapter is updated

The data in the RecyclerView is called the first time without issues. However when i refresh the data, for some reason all the items goes blank.
The MainActivity is this
class BusinessActivity : AppCompatActivity() {
private val businessViewModel: BusinessViewModel by viewModel()
private val imageLoader: ImageLoader by inject()
private lateinit var staggeredGridLayoutManager: StaggeredGridLayoutManager
private lateinit var skeleton: Skeleton
private val adapter: BusinessAdapter by lazy { BusinessAdapter(imageLoader, businessViewModel) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_business)
initToolbar()
skeleton = findViewById<SkeletonLayout>(R.id.skeletonLayout)
staggeredGridLayoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)
staggeredGridLayoutManager.gapStrategy = StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS
recycler_view.apply {
layoutManager = staggeredGridLayoutManager
adapter = this#BusinessActivity.adapter
setHasFixedSize(true)
}
setupSkeleton()
initializeObserverBusiness()
refreshBusiness.setOnRefreshListener {
refreshBusiness.isRefreshing = true
skeleton.showSkeleton()
businessViewModel.retrieveBusiness()
}
}
private fun initToolbar() {
setSupportActionBar(toolbar)
supportActionBar?.title = getString(R.string.app_name)
this.setSystemBarColor(this)
}
private fun setupSkeleton(){
skeleton = recycler_view.applySkeleton(R.layout.business_card, 6)
skeleton.showSkeleton()
}
private fun initializeObserverBusiness(){
businessViewModel.uiState.observe(this, Observer {
val dataState = it ?: return#Observer
if (!dataState.showProgress){
refreshBusiness.isRefreshing = false
skeleton.showOriginal()
}
if (dataState.business != null && !dataState.business.consumed){
dataState.business.consume()?.let { business ->
adapter.submitList(business)
}
}
if (dataState.error != null && !dataState.error.consumed){
dataState.error.consume()?.let { error ->
Toast.makeText(this, resources.getString(error), Toast.LENGTH_LONG).show()
}
}
})
}
}
and the Adapter for the RecyclerView, im currently using DiffCallback and ListAdapter due to a better performance.
class BusinessAdapter(var imageLoader: ImageLoader, var viewModel: BusinessViewModel) : ListAdapter<Business, BusinessViewHolder>(DIFF_CALLBACK){
companion object{
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Business>() {
override fun areItemsTheSame(oldItem: Business, newItem: Business) = oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: Business, newItem: Business) = oldItem == newItem
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = BusinessViewHolder.create(parent)
override fun onBindViewHolder(holder: BusinessViewHolder, position: Int) {
holder.bind(getItem(position), imageLoader, viewModel)
}
}
and the ViewHolder for the Adapter
class BusinessViewHolder constructor(override val containerView: View) : RecyclerView.ViewHolder(containerView), LayoutContainer {
fun bind(business: Business, imageLoader: ImageLoader, viewModel: BusinessViewModel) {
businessImage?.let { imageLoader.load("${BuildConfig.MY_URL}/gallery/${business.images[0]}", it) }
ownerBusiness.text = business.owner
businessName.text = business.name
cardBusiness.setOnClickListener {
viewModel.callDetailBusiness(business.id)
}
}
companion object {
fun create(parent: ViewGroup): BusinessViewHolder {
return BusinessViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.business_card, parent, false))
}
}
}
and the ViewModel
class BusinessViewModel (private val businessRepository: BusinessRepository): ViewModel() {
private val _uiState = MutableLiveData<BusinessDataState>()
val uiState: LiveData<BusinessDataState> get() = _uiState
val _showDetailBusiness = MutableLiveData<Int?>()
val showDetailBusiness: LiveData<Int?> get() = _showDetailBusiness
init {
retrieveBusiness()
}
fun retrieveBusiness(){
viewModelScope.launch {
runCatching {
emitUiState(showProgress = true)
businessRepository.retrieveBusiness()
}.onSuccess {
emitUiState(business = Event(it))
}.onFailure {
emitUiState(error = Event(R.string.internet_failure_error))
}
}
}
fun callDetailBusiness(businessId: Int) {
_showDetailBusiness.value = businessId
}
private fun emitUiState(showProgress: Boolean = false, business: Event<List<Business>>? = null, error: Event<Int>? = null){
val dataState = BusinessDataState(showProgress, business, error)
_uiState.value = dataState
}
data class BusinessDataState(val showProgress: Boolean, val business: Event<List<Business>>?, val error: Event<Int>?)
}
When the data is loaded for the first time i see this.
however when i apply the SwipeRefresh. I receive the data.
D/OkHttp: [{"id":18,"name":"Whatsup","owner":"Mi
Soledad","category":"ToDo",
but the RecyclerView won't attach the new information...

How to pass Retrofit onResponse Data to an Activity?

I want to pass retrofit response to Activity so that i can set data in the recyclerview adapter. I don't want to use LiveData or RxJava.
Here imageDetails is the list of Json Object and I want to pass it to MainActivity.
TrendingViewModel.kt
class TrendingViewModel : ViewModel() {
fun fetchGifs() {
val apiService = GiphyApi().getClient()?.create(ApiInterface::class.java)
val call = apiService?.getTrendingResults(20, Constants.API_KEY)
var imageDetails: List<ImageDetails>
call?.enqueue(object : retrofit2.Callback<GiphyResponse> {
override fun onResponse(call: Call<GiphyResponse>?, response: Response<GiphyResponse>?) {
imageDetails = response?.body()?.data!!
}
override fun onFailure(call: Call<GiphyResponse>?, t: Throwable?) {
}
})
}}
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var layoutManager: RecyclerView.LayoutManager
lateinit var adapter: RecyclerViewAdapter
lateinit var trendingViewModel: TrendingViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
val debugTree: Timber.DebugTree = Timber.DebugTree()
TrendingViewModel().fetchGifs()
Timber.plant(debugTree)
trendingViewModel = ViewModelProviders.of(this).get(TrendingViewModel::class.java)
trendingViewModel.fetchGifs()
layoutManager = GridLayoutManager(this, 3) as RecyclerView.LayoutManager
binding.recyclerview.layoutManager = layoutManager
adapter = RecyclerViewAdapter(this)
binding.recyclerview.adapter = adapter
adapter.setListData(//TODO I need the response data here)
}}
RecyclerViewAdapter.kt
Edit: Everthing is working fine but My list is getting updated after all the default function is called.
class RecyclerViewAdapter(context: Context) : RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>(){
private var gifList: List<ImageDetails>? = Collections.emptyList()
private var mContext: Context? = null
init {
this.mContext = context
}
fun setListData(list: List<ImageDetails>) {
gifList=list
Log.i("Size SetListData", gifList!!.size.toString())
//Here it is showing List size 20
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder? {
val binding = DataBindingUtil.inflate<RecyclerviewListItemBinding>(LayoutInflater.from(parent.context), R.layout.recyclerview_list_item,
parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
//val binding = holder.binding;
Log.i("Size SizeBindHolder",gifList?.size.toString())
//Size = 0
/*Glide.with(mContext)
.load(gifList?.get(position)?.images?.dimen?.url)
.into(holder.imageView)*/
}
override fun getItemCount(): Int {
Log.i("Size ItemCount",gifList?.size.toString())
// Size = 0
return gifList?.size!!
}
class ViewHolder(var binding: RecyclerviewListItemBinding) : RecyclerView.ViewHolder(binding.root) {
var imageView: ImageView
init {
this.binding = binding
imageView = binding.imageView
}
}
1- in your activity add:
public class MainActivity extends AppCompatActivity implements Observer {
....
}
2- implement the method update() in your activity:
#Override
public void update(Observable o, Object arg) {
}
3- create an Observable object:
public class RetrofitObservable extends Observable {
private static RetrofitObservable instance = null;
public static RetrofitObservable getInstance() {
if(instance == null) {
instance = new RetrofitObservable();
}
return instance;
}
public void notifyObserverWithResponse(Object response) {
setChanged();
notifyObservers(response);
}
}
4- in your activity onResume() add this line:
RetrofitObservable.getInstance().addObserver(this);
5- in your activity onPause() add this line:
RetrofitObservable.getInstance().deleteObserver(this);
6- in your Retrofit response, call this line:
RetrofitObservable.getInstance(). notifyObserverWithResponse(yourResponseHere);
7- in your activity update method, handle your response:
#Override
public void update(Observable o, Object arg) {
YourRetrofitResponse response = (YourRetrofitResponse) arg;
// make your changes here
}
You can use pass your desired method which needs to be called as functional parameter, try below here fetchGifs accepts one method as parameter & in MainActivity we are passing adapter.setListData to it as parameter
class TrendingViewModel : ViewModel() {
fun fetchGifs(callback: (giphyResponse: GiphyResponse) -> Any) {
val apiService = GiphyApi().getClient()?.create(ApiInterface::class.java)
val call = apiService?.getTrendingResults(20, Constants.API_KEY)
var imageDetails: List<ImageDetails>
call?.enqueue(object : retrofit2.Callback<GiphyResponse> {
override fun onResponse(call: Call<GiphyResponse>?, response: Response<GiphyResponse>?) {
imageDetails = response?.body()?.data!!
callback(imageDetails)
}
override fun onFailure(call: Call<GiphyResponse>?, t: Throwable?) {
}
})
}}
class MainActivity : AppCompatActivity() {
private lateinit var layoutManager: RecyclerView.LayoutManager
lateinit var adapter: RecyclerViewAdapter
lateinit var trendingViewModel: TrendingViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
val debugTree: Timber.DebugTree = Timber.DebugTree()
Timber.plant(debugTree)
trendingViewModel = ViewModelProviders.of(this).get(TrendingViewModel::class.java)
trendingViewModel.fetchGifs()
layoutManager = GridLayoutManager(this, 3) as RecyclerView.LayoutManager
binding.recyclerview.layoutManager = layoutManager
adapter = RecyclerViewAdapter(this)
binding.recyclerview.adapter = adapter
TrendingViewModel().fetchGifs(result -> adapter.setListData(result))
}}

Categories

Resources