Android "Exception while computing database live data." error when running test - android

I have a fragment which named FavoriteScreen.
FavoriteScreen has a favoriteScreenviewModel.
FavoriteScreen lists favorite movies and favorite movies are coming from Room Database.
Also, when pressed a film from recycleView, sets movie value in detailViewModel, detailScreen opens and detailScreen observing the detailScreenViewModel movie value.
When I make a test in FavoriteScreen, given error. What can I do it?
My favorite screen like this:
#AndroidEntryPoint
class FavoriteScreen #Inject constructor(var favoriteMovieAdapter: FavoriteMovieAdapter) :
Fragment() {
private var _binding: FragmentFavoriteScreenBinding? = null
private val fragmentFavoriteScreenBinding get() = _binding!!
lateinit var viewModel: FavoriteScreenViewModel
lateinit var detailViewModel: DetailScreenViewModel
lateinit var moviesRecyclerView: RecyclerView
var favoriteMovieList: List<FavoriteMovie> = listOf()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentFavoriteScreenBinding.inflate(inflater, container, false)
return fragmentFavoriteScreenBinding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(requireActivity())[FavoriteScreenViewModel::class.java]
detailViewModel = ViewModelProvider(requireActivity())[DetailScreenViewModel::class.java]
subscribeToObservers()
moviesRecyclerView = fragmentFavoriteScreenBinding.moviesListRecyclerFavorite
moviesRecyclerView.adapter = favoriteMovieAdapter
moviesRecyclerView.layoutManager =
LinearLayoutManager(requireContext())
favoriteMovieAdapter.setOnItemClickListener {
val selectedMovie =
MovieResult(
it.backdrop_path,
it.poster_path,
it.api_id,
it.original_language,
it.original_title,
it.title,
it.release_date,
it.overview,
it.popularity.toFloat(),
it.vote_average.toFloat(),
it.vote_count
)
detailViewModel.setItem(selectedMovie)
findNavController().navigate(R.id.action_favoriteScreen_to_detailScreen)
}
}
private fun subscribeToObservers() {
viewModel.favoriteMovies.observe(viewLifecycleOwner) {
favoriteMovieAdapter.movieList = it
setVisibility(it)
}
}
private fun setVisibility(list: List<FavoriteMovie>) {
if (list.isNotEmpty()) {
fragmentFavoriteScreenBinding.favoritesBackground.visibility = View.GONE
} else {
fragmentFavoriteScreenBinding.favoritesBackground.visibility = View.VISIBLE
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}}
My FavoriteScreenViewModel like this:
#HiltViewModel
class FavoriteScreenViewModel #Inject constructor(private val repository: MovieRepositoryInterface) :
ViewModel() {
val favoriteMovies = repository.getFavoriteMovies()
}
My FakeRepository like this:
class FakeMovieRepositoryTest : MovieRepositoryInterface {
private val favoriteMovies = mutableListOf<FavoriteMovie>()
private val favoriteMoviesLiveData = MutableLiveData<List<FavoriteMovie>>(favoriteMovies)
private val watchListMovies = mutableListOf<WatchListMovie>()
private val watchListMoviesLiveData = MutableLiveData<List<WatchListMovie>>(watchListMovies)
override suspend fun insertFavoriteMovie(movie: FavoriteMovie) {
favoriteMovies.add(movie)
refreshFavoriteMovieData()
}
override suspend fun deleteFavoriteMovie(api_id: Int) {
val item = favoriteMovies.find { it.api_id == api_id }
favoriteMovies.remove(item)
refreshFavoriteMovieData()
}
override fun getFavoriteMovies(): LiveData<List<FavoriteMovie>> {
return favoriteMoviesLiveData
}
override suspend fun checkIsInFavorites(api_id: Int): Boolean {
return favoriteMovies.find { it.api_id == api_id } != null
}
private fun refreshFavoriteMovieData() {
favoriteMoviesLiveData.postValue(favoriteMovies)
}
}
And my test class like this:
#MediumTest
#HiltAndroidTest
#ExperimentalCoroutinesApi
class FavoriteScreenTest {
#get:Rule
var hiltRule = HiltAndroidRule(this)
#get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()
#Inject
lateinit var fragmentFactory: FragmentFactory
lateinit var favoriteMovieResult: FavoriteMovie
lateinit var testViewModel: FavoriteScreenViewModel
lateinit var testDetailViewModel: DetailScreenViewModel
#Before
fun setup() {
hiltRule.inject()
favoriteMovieResult = FavoriteMovie(
"a",
"a",
1,
"a",
"a",
"a",
"2023-01-01",
"a",
"1",
"1",
1,
1
)
testViewModel = FavoriteScreenViewModel(FakeMovieRepositoryTest())
testDetailViewModel = DetailScreenViewModel(FakeMovieRepositoryTest())
testDetailViewModel.insertFavoriteMovie(favoriteMovieResult)
}
#Test
fun testWatchListVisibilityTrue() {
val navController = Mockito.mock(NavController::class.java)
launchFragmentInHiltContainer<FavoriteScreen>(factory = fragmentFactory) {
Navigation.setViewNavController(requireView(), navController)
viewModel = testViewModel
detailViewModel = testDetailViewModel
}
}
}

Related

Fragment screen switching when clicking recycler view item

Fragment1 exists in MainActivity and Fragment2 exists in Fragment1.
Fragment2 contains a recycler view, and inside the recycler view there are items with a move button. When I click the go button, I want to switch to a screen other than the RcyclerView with the items currently displayed in Fragment2.
adpater
class Quality_Material_Certification(
val material_name : String,
val use_type : String,
val standard : String,
val material_num : String
)
class QualityMaterialCertificationAdapter(private val dataset:
List<Quality_Material_Certification>) :RecyclerView.Adapter<QualityMaterialCertificationAdapter.QualityMaterialCertificationViewHolder>() {
class QualityMaterialCertificationViewHolder(val binding:
ItemQualityMaterialCertificationBinding) :
RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int):
QualityMaterialCertificationViewHolder {
val view =LayoutInflater.from(viewGroup.context).inflate(R.layout.item_quality_material_certification, viewGroup, false)
return QualityMaterialCertificationViewHolder(ItemQualityMaterialCertificationBinding.bind(view))
}
override fun onBindViewHolder(viewHolder: QualityMaterialCertificationViewHolder, position: Int) {
val listposition = dataset[position]
viewHolder.binding.materialName.text= listposition.material_name
viewHolder.binding.useType.text = listposition.use_type
viewHolder.binding.standard.text = listposition.standard
viewHolder.binding.goToMoreBtn.setOnClickListener {
setDataAtFragment(Fragment2(), listposition.material_num)
}
}
override fun getItemCount() = dataset.size
private fun setDataAtFragment(fragment: Fragment, material : String)
{
val bundle = Bundle()
val transaction = binding.root.supportFragmentManager?.beginTransaction()
bundle.putString("material", material)
fragment.arguments = bundle
transaction?.replace(R.id.appro_fl, fragment)?.commit()
}
}
fragment1
private var token : String? = null
private var const_code : String? = null
private var list = arrayListOf<Quality_Material_Certification>()
class Fragment1 : Fragment() {
private lateinit var binding:
FragmentQualityManagementFirefightingMaterialsCertificationBinding
var material: GetApproMaterListDTO? = null
lateinit var data: Quality_Material_Certification
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = FragmentQualityManagementFirefightingMaterialsCertificationBinding.inflate(layoutInflater)
binding.materialRecycler.layoutManager = LinearLayoutManager(context)
binding.materialRecycler.adapter = QualityMaterialCertificationAdapter(list)
arguments?.let {
token = it.getString("token").toString()
const_code = it.getString("cons_code").toString()
}
val dto = RequestDTO( "0", "9")
retrofit.requestservice(sysCd, token.toString(), dto).enqueue(object :
Callback<GetApproMaterListDTO> {
override fun onFailure(call: Call<GetApproMaterListDTO>, t: Throwable) { Log.d("retrofit", t.toString()) }
#SuppressLint("NotifyDataSetChanged")
override fun onResponse(call: Call<GetApproMaterListDTO>, response: Response<GetApproMaterListDTO>) {
material = response.body()
list.clear()
for (i in 0 until material?.value?.list!!.size) {
val material_name = material?.value?.list?.get(i)?.material_name.toString()
val use_type = material?.value?.list?.get(i)?.use_type.toString()
val standard = material?.value?.list?.get(i)?.standard.toString()
val material_num = material?.value?.list?.get(i)?.material_num.toString()
data = Quality_Material_Certification(material_name, use_type, standard ,material_num )
list.add(data)
}
binding.materialRecycler.adapter?.notifyDataSetChanged()
}
})
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return binding.root
}
companion object {
#JvmStatic
fun newInstance(param1: String, param2: String) =
Fragment1().apply {
arguments = Bundle().apply {
}
}
}
}
modified comment opinion
apdapter
interface clicktoDetail{
fun onClickDetail(model : CertificationDTO)
}
class CertificationAdapter(
private val context: Context,
private val dataset: List<CertificationDTO>,
private val clickListener: clicktoDetail)
: RecyclerView.Adapter<QualityMaterialCertificationAdapter.ChangeHolder>() {
inner class ChangeHolder(val binding: ItemCertificationBinding) : RecyclerView.ViewHolder(binding.root){
//val btn :Button = button.findViewById(R.id.go_to_more_btn)
init{
binding.goToMoreBtn.setOnClickListener { clickListener.onClickDetail(dataset[position]) }
}
}
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ChangeHolder {
val view = LayoutInflater.from(viewGroup.context).inflate(R.layout.item_certification, viewGroup, false)
return ChangeHolder(ItemCertificationBinding.bind(view))
}
override fun onBindViewHolder(viewHolder: ChangeHolder, position: Int) {
val listposition = dataset[position]
viewHolder.binding.materialName.text= listposition.material_name
viewHolder.binding.useType.text = listposition.use_type
viewHolder.binding.standard.text = listposition.standard
viewHolder.binding.madeCompanyName.text = listposition.produce_co
/* viewHolder.binding.goToMoreBtn.setOnClickListener {
val intent = Intent(context, Fragment1::class.java)
intent.putExtra("cons_code", listposition.project_const)
intent.run{
context.startActivity(this)
(context as Activity).finish()
}
}*/
}
override fun getItemCount() = dataset.size
}
Fragment
private var token : String? = null
private var const_code : String? = null
private var material_list = arrayListOf<Quality_Material_CertificationDTO>()
class Certification_Fragment : Fragment() {
private lateinit var binding: FragmentQualityManagementFirefightingMaterialsCertificationBinding
var material: GetListDTO? = null
lateinit var material_data : Quality_Material_CertificationDTO
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = FragmentCertificationBinding.inflate(layoutInflater)
val retrofitApproMaterList = RetrofitC("http://")
val GetApproMaterListService: GetApproMaterListService = retrofitApproMaterList.create(GetListService::class.java)
binding.materialRecycler.layoutManager = LinearLayoutManager(context)
binding.materialRecycler.adapter = CertificationAdapter(requireContext(), material_list, GotoDetail())
arguments?.let {
token = it.getString("token").toString()
const_code = it.getString("cons_code").toString()
}
val mdto = RequestDTO("", "")
GetApproMaterListService.requestappromaterial(sysCd, token, mdto).enqueue(object :
Callback<GetListDTO> {
override fun onFailure(call: Call<GetListDTO>, t: Throwable) { Log.d("retrofit", t.toString()) }
#SuppressLint("NotifyDataSetChanged")
override fun onResponse(call: Call<GetAListDTO>, response: Response<GetListDTO>) {
material = response.body()
material_list.clear()
for (i in 0 until material?.value?.list!!.size) {
val material_name = material?.value?.list?.get(i)?.material_name.toString()
val use_type = material?.value?.list?.get(i)?.use_type.toString()
val standard = material?.value?.list?.get(i)?.standard.toString()
val produce_co = material?.value?.list?.get(i)?.produce_co.toString()
val material_num = material?.value?.list?.get(i)?.material_num.toString()
material_data = Quality_Material_CertificationDTO(material_name, use_type, standard, produce_co ,material_num)
material_list.add(material_data)
CertificationAdapter(requireContext(), material_list, GotoDetail())
}
binding.materialRecycler.adapter?.notifyDataSetChanged()
}
})
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return binding.root
}
companion object {
#JvmStatic
fun newInstance(param1: String, param2: String) =
Quality_Management_Firefighting_Materials_Certification_Fragment().apply {
arguments = Bundle().apply {
}
}
}
class GotoDetail : Fragment(), clicktoDetail{
override fun onClickDetail(model: Quality_Material_CertificationDTO) {
val bundle = Bundle()
val transaction = activity?.supportFragmentManager?.beginTransaction()
bundle.putString("cons_code", const_code)
bundle.putString("token", token)
Fragment().arguments = bundle
transaction?.replace(R.id.appro_fl, Certification_More_Fragment())!!.commit()
}
}
}
You are trying to access activities and fragments inside your adapter class which is incorrect. Never do that! Instead, create an item click listener and create a reference to it in your activity. This way you can handle item click in your activity and perform fragment transactions.
Here, You can take help on how to do so by making an onClickInterface

how to add functions to onStart () | Kotlin

I have a problem because I am trying to add an onReceiptsAdd () function to onStart () but I don't know how to make it work. how to add onReceiptsAdd () to onStart ()
here is my code:
class ScanFragment : Fragment(), OnReceiptsItemAdd {
private var _binding: FragmentScanBinding? = null
private val binding get() = _binding!!
private val scanVm by viewModels<ScanViewModel>()
private val adapter = ReceiptsAdapter(this)
private val SCAN_DEBUG = "SCAN_DEBUG"
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
_binding = FragmentScanBinding.inflate(inflater, container, false)
// Inflate the layout for this fragment
return binding.root
}
override fun onStart() {
super.onStart()
val value = binding.etBlank.text?.trim().toString()
val from = binding.etBlank.text?.trim().toString()
val image = binding.etBlank.text?.trim().toString()
val rootRef = FirebaseFirestore.getInstance()
val usersRef = rootRef.collection("receipts")
val auth = FirebaseAuth.getInstance()
auth.currentUser?.apply {
usersRef.document(uid).set(mapOf(
"id" to uid,
"from" to from,
"value" to value,
"image" to image,
)).addOnCompleteListener { task ->
if (task.isSuccessful) {
Log.d("TAG", "User successfully added.")
} else {
Log.d("TAG", task.exception!!.message!!)
}
}
}
}
override fun onReceiptsAdd(receipts: dataReceipts, position: Int) {
scanVm.addFavReceipt(receipts)
}
}

Testing a Fragment Scenario with ViewBinding

I'm trying to test a fragment that uses viewBinding to show the views, and a viewModel to fetch that data.
I want to write a UI test to see if certain data is visible or not, but so fare I've had no luck and I'm hoping somebody can help me as I'm still very new to UI testing.
So far I tried mocking the viewModel, the liveData and the viewBinding, but to no success
Here are a few example classes of what I have tried to do
My ViewModel:
private val bike: MutableLiveData<Bike> = MutableLiveData()
val getBike: LiveData<BikeType>
get() = bikeType
fun getBike() {
BikeService().getBike(bikeId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
bike.postValue(it)
}, {
Timber.e(it)
}).let { disposeBag.add(it) }
}
}
}
My Fragment
class BikeFragment : AppAbstractBaseFragment<Any>(), BikeView,
OnBackPressedListener {
var mBinding: FragmentBikeBinding? = null
var viewModel: BikeViewModel? = null
var cancellable: Boolean = false
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
mBinding = FragmentBikeBinding.inflate(inflater, container, false)
return mBinding?.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (viewModel == null) {
viewModel = ViewModelProvider(this).get(BikeViewModel::class.java)
}
mBinding?.apply {
this.view = this#BikeDashboardFragment
viewModel?.getBike?.observe(viewLifecycleOwner, { newBike ->
bike = newBike
})
}
viewModel?.getBike()
}
The Test
class BikeTest {
#get:Rule
val screenshotTestRule = ScreenshotTestRule()
#Rule
#JvmField
val dataBindingIdlingResourceRule = DataBindingIdlingResourceRule()
#Rule
#JvmField
var instantExecutor = InstantTaskExecutorRule()
private var scenario: FragmentScenario<BikeFragment>? = null
private var bikeData = mockk<MutableLiveData<Bike>>()
private var viewModel = mockk<BikeViewModel>(relaxed = true)
private val lifecycleOwner: LifecycleOwner = mockk()
private var fakeBike =
Bike(id = 1, cancellable = true, linkable = true, ownerName = "Joske")
var context: Context? = null
#Before
fun setUp() {
val app = ApplicationProvider.getApplicationContext<BaseApplication>()
context = app.applicationContext
}
#Test
fun loadBikeSeeTheRightBikeData() {
scenario = launchFragmentInContainer(
themeResId = R.style.Theme_Brand
)
dataBindingIdlingResourceRule.monitorFragment(scenario!!)
scenario?.onFragment {
it.mBinding?.bike = fakeBike
onView(withId(R.id.ownerNameTextView)).check(matches(withText("Klaartje")))
}
}
}

Making more than one Api call with retrofit and paging

I'm trying to use paging with retrofit. But i have to make more than one calls for filtering or changing the rover(it is a nasa pictures app). But my app making Api call every second and that crashs it. I tried it with livedata also with flow but it didnt work.
There are three fragment execute same prosesses in tab layout with View Pager these are curiosityFragment, SpiritFragment, OpportunityFragment
object RetrofitInstance {
private val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
private val retrofit by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(MoshiConverterFactory.create(moshi)).baseUrl(BASE_URL)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
}
val api : SimpleApi by lazy {
retrofit.create(SimpleApi::class.java)
}}
interface SimpleApi {
#GET("mars-photos/api/v1/rovers/{name}/photos?sol=1000&api_key=DEMO_KEY")
fun getPhotos(#Path("name") name : String,
#Query("per_page")per_page:Int?,
#Query("page") page: Int):
Single<AllPhotos>
class DataSource(name:String) : RxPagingSource<Int,Photo>(){
var name :String
init{
this.name = name
}
override fun getRefreshKey(state: PagingState<Int, Photo>): Int? {
return null
}
override fun loadSingle(params: LoadParams<Int>): Single<LoadResult<Int, Photo>> {
val page = params.key ?:1
return RetrofitInstance.api.getPhotos(name,params.loadSize,page)
.subscribeOn(Schedulers.io())
.map {toLoadResult(it,page)}
.onErrorReturn { LoadResult.Error(it) }
}
private fun toLoadResult(data: AllPhotos,page : Int):LoadResult<Int,Photo>{
return LoadResult.Page(
data = data.photos,
prevKey = if(page==1) null else page-1,
nextKey = page.plus(1)
)
}
}
class ViewModelDataSource (application: Application):AndroidViewModel(application) {
fun getPhotosLiveData(name : String):LiveData<PagingData<Photo>>{
return Pager(
config = PagingConfig(pageSize = 10),
pagingSourceFactory = {
DataSource(name)
},
).liveData
}
}
class CuriosityFragment : Fragment() {
private lateinit var binding:FragmentCuriosityBinding
lateinit var mApiViewModel : ViewModelDataSource
private lateinit var curiosityAdapter: AdapterCuriosity
var hasLoadedOnce = false
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentCuriosityBinding.inflate(inflater,container,false)
mApiViewModel = ViewModelProvider(this).get(ViewModelDataSource::class.java)
setupRecyclerView()
loaddata()
return binding.root
}
fun setupRecyclerView(){
curiosityAdapter = AdapterCuriosity()
binding.recyclerViewCriosity.apply {
adapter = curiosityAdapter
layoutManager = LinearLayoutManager(requireContext())
}
}
fun loaddata(){
mApiViewModel.getPhotosLiveData("curiosity").observe(viewLifecycleOwner, Observer {
curiosityAdapter.submitData(this.lifecycle,it)})
}
class OpportunityFragment : Fragment() {
private lateinit var binding: FragmentOppurtunityBinding
private lateinit var mApiViewModel: ViewModelDataSource
private lateinit var recyclerView: RecyclerView
private lateinit var opportunityAdapter:AdapterOpportunity
var hasLoadedOnce = false
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentOppurtunityBinding.inflate(inflater, container, false)
recyclerView = binding.recyclerViewOpportunity
mApiViewModel = ViewModelProvider(this).get(ViewModelDataSource::class.java)
setupRecyclerView()
loaddata()
setHasOptionsMenu(true)
return binding.root
}
fun setupRecyclerView(){
opportunityAdapter = AdapterOpportunity()
binding.recyclerViewOpportunity.apply {
adapter = opportunityAdapter
layoutManager = LinearLayoutManager(requireContext())
}
}
fun loaddata(){
mApiViewModel.getPhotosLiveData("opportunity").observe(viewLifecycleOwner, Observer {
opportunityAdapter.submitData(this.lifecycle,it)})
}
class SpiritFragment : Fragment() {
private lateinit var binding: FragmentSpiritBinding
private lateinit var mApiViewModel : ViewModelDataSource
private lateinit var spiritAdapter:AdapterSpirit
lateinit var recyclerView: RecyclerView
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentSpiritBinding.inflate(inflater, container, false)
recyclerView = binding.recyclerViewSpirit
mApiViewModel = ViewModelProvider(this).get(ViewModelDataSource::class.java)
setupRecyclerView()
loaddata()
setHasOptionsMenu(true)
return binding.root
}
fun setupRecyclerView(){
spiritAdapter = AdapterSpirit()
binding.recyclerViewSpirit.apply {
adapter = spiritAdapter
layoutManager = LinearLayoutManager(requireContext())
}
}
fun loaddata(){
mApiViewModel.getPhotosLiveData("spirit").observe(viewLifecycleOwner, Observer {
spiritAdapter.submitData(this.lifecycle,it)})
}

Sometimes my ap crash when retrieve data with retrofit : D/AndroidRuntime: Shutting down VM?

this is my Retrofit retrieve code :
the error came from this line ==>> val respon = response.body()!!
( java.lang.NullPointerException
at com.xfath.hormart.fragments.homechildfragments.ChildHomeFragment$getProducts$1.onResponse(ChildHomeFragment.kt:124 )
class ChildHomeFragment : Fragment(){
private lateinit var s: SharedPreference
private var listImageSliderHomes: ArrayList<ImageSliderHome> = ArrayList()
private var listProducts: ArrayList<Products> = ArrayList()
private lateinit var sliderView: SliderView
private lateinit var rvProductBaru: RecyclerView
private lateinit var rvElektronik: RecyclerView
private lateinit var rvPribadi: RecyclerView
private lateinit var ivNotif: ImageButton
private lateinit var uidhome: TextView
private lateinit var svhome: NestedScrollView
private lateinit var mSearchView: SearchView
private lateinit var mSwipeRefreshLayout: SwipeRefreshLayout
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
getSlideImage()
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_child_home, container, false)
init(view)
getProducts()
swipeRefresh()
s = SharedPreference(activity!!)
return view
}
private fun getProducts() {
ApiConfig.instanceRetrofit.getproduct().enqueue(object : Callback<ResponseModel> {
override fun onResponse(call: Call<ResponseModel>, response: Response<ResponseModel>) {
val respon = response.body()!!
if (respon.success == 1) {
listProducts = respon.products
displayProduct()
}
}
override fun onFailure(call: Call<ResponseModel>, t: Throwable) {
Log.v(TAG, "Error:" + t.message)
}
})
}
private fun displayProduct() {
val layoutManager = LinearLayoutManager(activity)
layoutManager.orientation = LinearLayoutManager.HORIZONTAL
rvProductBaru.adapter = ProductAdapter(listProducts)
rvProductBaru.layoutManager = layoutManager
}
}
thanks in advance..
This is meant that the response.body() returns null.
You should always do null checking for it or you can use let to avoid NPE.
PS: Avoid using !! in kotlin as it may throw NPE when the variable is null.
response.body()?.let { respon ->
if (respon.success == 1) {
listProducts = respon.products
displayProduct()
}
}

Categories

Resources