AssistedFactory in Dagger-Hilt property doesn't Initialize - android

I want to insert parameter during runtime by using Dagger-Hilt. I knew that it could be achieved using annotation that hilt is providing i.e #AssistedFactory. I m implementing it the same way, but still it throws an error lateinit property isn't initialized. I couldn't find where I go wrong if some can help me in this regard. Following is what I have done so far.
Timer.kt
#AssistedFactory
interface TimerFactory {
fun create(
#Assisted("millis")
millisInFuture: Long,
#Assisted("interval")
countDownInterval: Long
): Timer
}
var isRunning = true
class Timer #AssistedInject constructor(
#Assisted("millis") val millisInFuture: Long,
#Assisted("interval") val countDownInterval: Long
) :
CountDownTimer(millisInFuture, countDownInterval) {
var otpView: TextView? = null
companion object {
var remainMilli: Long = 0
}
override fun onTick(millisInFuture: Long) {
remainMilli = millisInFuture
otpView?.text = (millisInFuture / 1000).toString() + "seconds"
}
override fun onFinish() {
isRunning = false
remainMilli = 0
}
fun setTimerView(view: View) {
otpView = view as TextView
}
}
Fragment.kt
#Inject
lateinit var timerFactory: TimerFactory
private lateinit var timer: Timer
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setTimer()
timer.setTimerView(binding.pvOtp)
}
private fun setTimer() {
if (!isRunning) {
timer.cancel()
isRunning = true
} else {
if (remainMilli == 0L) {
timer = timerFactory.create(30000, 1000)// lateinit property timerFactory has not been initialized
timer.start()
isRunning = false
} else {
timer = timerFactory.create(remainMilli, 1000)
timer.start()
isRunning = false
}
}
}
MainActivity & ApplicationAcitivty
#AndroidEntryPoint
class MainAcitivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
}
#HiltAndroidApp
class Sample: Application() {
override fun onCreate() {
super.onCreate()
}
}
Menifest.xml
<application
android:name=".Sample"
...</application>
GeneratedFile OTPFragment_MembersInjector.kt
#DaggerGenerated
#SuppressWarnings({
"unchecked",
"rawtypes"
})
public final class OTPFragment_MembersInjector implements MembersInjector<OTPFragment> {
private final Provider<TimerFactory> timerFactoryProvider;
public OTPFragment_MembersInjector(Provider<TimerFactory> timerFactoryProvider) {
this.timerFactoryProvider = timerFactoryProvider;
}
public static MembersInjector<OTPFragment> create(Provider<TimerFactory> timerFactoryProvider) {
return new OTPFragment_MembersInjector(timerFactoryProvider);
}
#Override
public void injectMembers(OTPFragment instance) {
injectTimerFactory(instance, timerFactoryProvider.get());
}
#InjectedFieldSignature("com.jsglobal.ui.fragment.auth_fragment.OTPFragment.timerFactory")
public static void injectTimerFactory(OTPFragment instance, TimerFactory timerFactory) {
instance.timerFactory = timerFactory;
}
}
Any Help would be really appreciated. Thanks

Related

How can i get my args.field from my activity to my viewmodel

I want to use my args.breweryName from my reviewActivity in my reviewViewModel but i don't know what's the best way to do it. I have tried using savestatehandle but i'm not experienced with that. I'm new to programming with kotlin so i would appreciate the help!
My ReviewActivity
class ReviewActivity : AppCompatActivity() {
val breweryText: TextView
get() = findViewById(R.id.breweryName)
private val args: ReviewActivityArgs by navArgs<ReviewActivityArgs>()
private var shownFragment: Fragment? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_review)
initView()
if (savedInstanceState == null) {
showFragment(ReviewFragment.newInstance())
}
breweryText.text = args.breweryName
}
fun test(): String {
return args.breweryName
}
private fun initView() {
val button : FloatingActionButton = findViewById(R.id.add)
showFragment(ReviewFragment.newInstance())
button.setOnClickListener { showSaveDialog() }
}
private fun showFragment(fragment: Fragment) {
val fragmentTransaction: FragmentTransaction = supportFragmentManager.beginTransaction()
fragmentTransaction.replace(R.id.fragmentHolder, fragment)
fragmentTransaction.commitNow()
shownFragment = fragment
}
private fun showSaveDialog() {
val dialogFragment: DialogFragment
val tag: String
dialogFragment = ReviewDialog.newInstance(null, null, args.breweryName)
tag = ReviewDialog.TAG_DIALOG_REVIEW_SAVE
dialogFragment.show(supportFragmentManager, tag)
}
My ReviewViewModel
class ReviewViewModel constructor(application: Application) : AndroidViewModel(application) {
private val reviewDao: ReviewDao = ReviewsDatabase.getDatabase(application).reviewDao()
private val userDao: UserDao = ReviewsDatabase.getDatabase(application).userDao()
val data = MutableLiveData<String>()
val reviewList: LiveData<List<Review>>
val userList: LiveData<List<User>>
fun data(item: String) {
data.value = item
}
init {
reviewList = reviewDao.allReviews
userList = userDao.allUsers
}
fun insert(vararg reviews: Review) {
reviewDao.insert(*reviews)
}
fun update(review: Review) {
reviewDao.update(review)
}
fun deleteAll() {
reviewDao.deleteAll()
}
}

android.content.SharedPreferences is not nullable, but is being provided by #Singleton #Provides #org.jetbrains.annotations.Nullable a

I am developing new app and implemented shared preferences in my appModule.kt but when I run project I am getting following errors
Task :app:hiltJavaCompileDebug
C:\Users\Yodgorbek\RunTrackerApp\app\build\generated\hilt\component_sources\debug\com\example\runtrackerapp\BaseApplication_HiltComponents.java:136: error: [Dagger/Nullable] android.content.SharedPreferences is not nullable, but is being provided by #Singleton #Provides #org.jetbrains.annotations.Nullable android.content.SharedPreferences com.example.runtrackerapp.di.AppModule.provideSharedPreferences(#dagger.hilt.android.qualifiers.ApplicationContext android.content.Context)
public abstract static class SingletonC implements BaseApplication_GeneratedInjector,
^
android.content.SharedPreferences is injected at
com.example.runtrackerapp.di.AppModule.provideWeight(sharedPref)
java.lang.Float is injected at
com.example.runtrackerapp.ui.fragments.TrackingFragment.setWeight(<set-?>)
com.example.runtrackerapp.ui.fragments.TrackingFragment is injected at
com.example.runtrackerapp.ui.fragments.TrackingFragment_GeneratedInjector.injectTrackingFragment(com.example.runtrackerapp.ui.fragments.TrackingFragment) [com.example.runtrackerapp.BaseApplication_HiltComponents.SingletonC ? com.example.runtrackerapp.BaseApplication_HiltComponents.ActivityRetainedC ? com.example.runtrackerapp.BaseApplication_HiltComponents.ActivityC ? com.example.runtrackerapp.BaseApplication_HiltComponents.FragmentC]
C:\Users\Yodgorbek\RunTrackerApp\app\build\generated\hilt\component_sources\debug\com\example\runtrackerapp\BaseApplication_HiltComponents.java:136: error: [Dagger/Nullable] android.content.SharedPreferences is not nullable, but is being provided by #Singleton #Provides #org.jetbrains.annotations.Nullable android.content.SharedPreferences com.example.runtrackerapp.di.AppModule.provideSharedPreferences(#dagger.hilt.android.qualifiers.ApplicationContext android.content.Context)
public abstract static class SingletonC implements BaseApplication_GeneratedInjector,
^
android.content.SharedPreferences is injected at
com.example.runtrackerapp.ui.fragments.SetupFragment.sharedPref
com.example.runtrackerapp.ui.fragments.SetupFragment is injected at
com.example.runtrackerapp.ui.fragments.SetupFragment_GeneratedInjector.injectSetupFragment(com.example.runtrackerapp.ui.fragments.SetupFragment) [com.example.runtrackerapp.BaseApplication_HiltComponents.SingletonC ? com.example.runtrackerapp.BaseApplication_HiltComponents.ActivityRetainedC ? com.example.runtrackerapp.BaseApplication_HiltComponents.ActivityC ? com.example.runtrackerapp.BaseApplication_HiltComponents.FragmentC]
C:\Users\Yodgorbek\RunTrackerApp\app\build\generated\hilt\component_sources\debug\com\example\runtrackerapp\BaseApplication_HiltComponents.java:136: error: [Dagger/Nullable] android.content.SharedPreferences is not nullable, but is being provided by #Singleton #Provides #org.jetbrains.annotations.Nullable android.content.SharedPreferences com.example.runtrackerapp.di.AppModule.provideSharedPreferences(#dagger.hilt.android.qualifiers.ApplicationContext android.content.Context)
public abstract static class SingletonC implements BaseApplication_GeneratedInjector,
^
android.content.SharedPreferences is injected at
com.example.runtrackerapp.di.AppModule.provideFirstTimeToggle(sharedPref)
java.lang.Boolean is injected at
com.example.runtrackerapp.ui.fragments.SetupFragment.setFirstAppOpen(<set-?>)
com.example.runtrackerapp.ui.fragments.SetupFragment is injected at
com.example.runtrackerapp.ui.fragments.SetupFragment_GeneratedInjector.injectSetupFragment(com.example.runtrackerapp.ui.fragments.SetupFragment) [com.example.runtrackerapp.BaseApplication_HiltComponents.SingletonC ? com.example.runtrackerapp.BaseApplication_HiltComponents.ActivityRetainedC ? com.example.runtrackerapp.BaseApplication_HiltComponents.ActivityC ? com.example.runtrackerapp.BaseApplication_HiltComponents.FragmentC]
3 errors
below my appModule.kt
#Module
#InstallIn(SingletonComponent::class)
object AppModule {
#Singleton
#Provides
fun provideRunningDatabase(
#ApplicationContext app: Context
) = Room.databaseBuilder(
app,
RunningDatabase::class.java,
RUNNING_DATABASE_NAME
).build()
#Singleton
#Provides
fun provideRunDao(db: RunningDatabase) = db.getRunDao()
#Singleton
#Provides
fun provideSharedPreferences(#ApplicationContext app: Context): SharedPreferences? {
val sharedPreferences = app.getSharedPreferences(SHARED_PREFERENCES_NAME, MODE_PRIVATE)
return sharedPreferences
}
#Singleton
#Provides
fun provideName(sharedPref: SharedPreferences) = sharedPref.getString(KEY_NAME, "") ?: ""
#Singleton
#Provides
fun provideWeight(sharedPref: SharedPreferences) = sharedPref.getFloat(KEY_WEIGHT, 80f)
#Singleton
#Provides
fun provideFirstTimeToggle(sharedPref: SharedPreferences) =
sharedPref.getBoolean(KEY_FIRST_TIME_TOGGLE, true)
}
below SetupFragment.kt
#AndroidEntryPoint
class SetupFragment : Fragment() {
private var _binding: FragmentSetupBinding? = null
private val binding get() = _binding!!
#Inject
lateinit var sharedPref: SharedPreferences
#set:Inject
var isFirstAppOpen = true
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// inflate the layout and bind to the _binding
_binding = FragmentSetupBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if(!isFirstAppOpen){
val navOptions = NavOptions.Builder()
.setPopUpTo(R.id.setupFragment, true)
.build()
findNavController().navigate(
R.id.action_setupFragment_to_runFragment,
savedInstanceState,
navOptions)
}
binding.tvContinue.setOnClickListener {
val success = writePersonalDataToSharedPref()
if (success){
findNavController().navigate(R.id.action_setupFragment_to_runFragment)
}else{
Snackbar.make(requireView(), "Please enter all the fields", Snackbar.LENGTH_SHORT).show()
}
}
}
private fun writePersonalDataToSharedPref(): Boolean {
val name = binding.etName.text.toString()
val weight = binding.etWeight.text.toString()
if(name.isEmpty() || weight.isEmpty()) {
return false
}
sharedPref.edit()
.putString(KEY_NAME, name)
.putFloat(KEY_WEIGHT, weight.toFloat())
.putBoolean(KEY_FIRST_TIME_TOGGLE, false)
.apply()
val toolbarText = "Let's go, $name!"
(requireActivity() as ActivityMainBinding).tvToolbarTitle.text = toolbarText
return true
}
}
below TrackingFragment.kt
#AndroidEntryPoint
class TrackingFragment : Fragment(R.layout.fragment_tracking) {
private val viewModel: MainViewModel by viewModels()
private var isTracking = false
private var pathPoints = mutableListOf<Polyline>()
private var map: GoogleMap? = null
private var curTimeInMillis = 0L
private var _binding: FragmentTrackingBinding? = null
private val binding get() = _binding!!
private var menu: Menu? = null
#set:Inject
var weight = 80f
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
setHasOptionsMenu(true)
_binding = FragmentTrackingBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.mapView.onCreate(savedInstanceState)
binding.btnToggleRun.setOnClickListener {
toggleRun()
}
binding.btnFinishRun.setOnClickListener {
zoomToSeeWholeTrack()
endRunAndSaveToDb()
}
binding.mapView.getMapAsync {
map = it
addAllPolylines()
}
subscribeToObservers()
}
private fun subscribeToObservers() {
TrackingService.isTracking.observe(viewLifecycleOwner, Observer {
updateTracking(it)
})
TrackingService.pathPoints.observe(viewLifecycleOwner, Observer {
pathPoints = it
addLatestPolyline()
moveCameraToUser()
})
TrackingService.timeRunInMillis.observe(viewLifecycleOwner, Observer {
curTimeInMillis = it
val formattedTime = TrackingUtility.getFormattedStopWatchTime(curTimeInMillis, true)
binding.tvTimer.text = formattedTime
})
}
private fun toggleRun() {
if(isTracking) {
menu?.getItem(0)?.isVisible = true
sendCommandToService(ACTION_PAUSE_SERVICE)
} else {
sendCommandToService(ACTION_START_OR_RESUME_SERVICE)
}
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.toolbar_tracking_menu, menu)
this.menu = menu
}
override fun onPrepareOptionsMenu(menu: Menu) {
super.onPrepareOptionsMenu(menu)
if(curTimeInMillis > 0L) {
this.menu?.getItem(0)?.isVisible = true
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId) {
R.id.miCancelTracking -> {
showCancelTrackingDialog()
}
}
return super.onOptionsItemSelected(item)
}
private fun showCancelTrackingDialog() {
val dialog = MaterialAlertDialogBuilder(requireContext(), R.style.AlertDialogTheme)
.setTitle("Cancel the Run?")
.setMessage("Are you sure to cancel the current run and delete all its data?")
.setIcon(R.drawable.ic_delete)
.setPositiveButton("Yes") { _, _ ->
stopRun()
}
.setNegativeButton("No") { dialogInterface, _ ->
dialogInterface.cancel()
}
.create()
dialog.show()
}
private fun stopRun() {
sendCommandToService(ACTION_STOP_SERVICE)
findNavController().navigate(R.id.action_trackingFragment_to_runFragment)
}
private fun updateTracking(isTracking: Boolean) {
this.isTracking = isTracking
if(!isTracking) {
binding.btnToggleRun.text = "Start"
binding.btnFinishRun.visibility = View.VISIBLE
} else {
binding.btnToggleRun.text = "Stop"
menu?.getItem(0)?.isVisible = true
binding.btnFinishRun.visibility = View.GONE
}
}
private fun moveCameraToUser() {
if(pathPoints.isNotEmpty() && pathPoints.last().isNotEmpty()) {
map?.animateCamera(
CameraUpdateFactory.newLatLngZoom(
pathPoints.last().last(),
MAP_ZOOM
)
)
}
}
private fun zoomToSeeWholeTrack(){
val bounds = LatLngBounds.builder()
for(polyline in pathPoints){
for(pos in polyline){
bounds.include(pos)
}
}
map?.moveCamera(
CameraUpdateFactory.newLatLngBounds(
bounds.build(),
binding.mapView.width,
binding.mapView.height,
(binding.mapView.height * 0.05f).toInt()
)
)
}
private fun endRunAndSaveToDb(){
map?.snapshot { bmp ->
var distanceInMeters = 0
for (polyline in pathPoints){
distanceInMeters+= TrackingUtility.calculatePolylineLength(polyline).toInt()
}
val avgSpeed = round((distanceInMeters / 1000f) / (curTimeInMillis / 1000f / 60 / 60) * 10) / 10f
val dataTimestamp = Calendar.getInstance().timeInMillis
val caloriesBurned = ((distanceInMeters / 1000f) * weight).toInt()
val run = Run(bmp,dataTimestamp, avgSpeed,distanceInMeters, curTimeInMillis, caloriesBurned)
viewModel.insertRun(run)
Snackbar.make(
requireActivity().findViewById(R.id.rootView),
"Run saved successfully",
Snackbar.LENGTH_LONG
).show()
stopRun()
}
}
private fun addAllPolylines() {
for(polyline in pathPoints) {
val polylineOptions = PolylineOptions()
.color(POLYLINE_COLOR)
.width(POLYLINE_WIDTH)
.addAll(polyline)
map?.addPolyline(polylineOptions)
}
}
private fun addLatestPolyline() {
if(pathPoints.isNotEmpty() && pathPoints.last().size > 1) {
val preLastLatLng = pathPoints.last()[pathPoints.last().size - 2]
val lastLatLng = pathPoints.last().last()
val polylineOptions = PolylineOptions()
.color(POLYLINE_COLOR)
.width(POLYLINE_WIDTH)
.add(preLastLatLng)
.add(lastLatLng)
map?.addPolyline(polylineOptions)
}
}
private fun sendCommandToService(action: String) =
Intent(requireContext(), TrackingService::class.java).also {
it.action = action
requireContext().startService(it)
}
override fun onResume() {
super.onResume()
binding.mapView?.onResume()
}
override fun onStart() {
super.onStart()
binding.mapView?.onStart()
}
override fun onStop() {
super.onStop()
binding.mapView?.onStop()
}
override fun onPause() {
super.onPause()
binding.mapView?.onPause()
}
override fun onLowMemory() {
super.onLowMemory()
binding.mapView?.onLowMemory()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
binding.mapView?.onSaveInstanceState(outState)
}
}
I want to know where I am making mistake I have followed all stackoverflow answer it did not solve my issue
A provider should not be nullable in your case provideSharedPreferences..
Remove Nullble from return type.
#Singleton
#Provides
fun provideSharedPreferences(#ApplicationContext app: Context): SharedPreferences {
val sharedPreferences = app.getSharedPreferences(SHARED_PREFERENCES_NAME, MODE_PRIVATE)
return sharedPreferences
}

Lifecycle in Activity is not triggered in ViewModel

I am trying to execute a method(fun onCreateViewModel()) in viewModel whenever the onCreate of the Activity is invoked. But the method is not getting executed.
ViewModel
class MainActivityViewModel(startingCount : Int) : ViewModel(), LifecycleObserver {
var count = 0
init {
count = startingCount
}
fun getCurrentCount(): Int{
return count
}
fun getUpdatedCount(): Int {
count ++
return count
}
#OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
public fun onCreateViewModel(){
Log.i("Jts"," ViewModel created")
}
}
Activity
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private var user = User("Jeffin T", "26")
private lateinit var mainActivityViewModel: MainActivityViewModel
private lateinit var mainActivityViewModelFactory: MainActivityViewModelFactory
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// mainActivityViewModel = ViewModelProviders.of()
mainActivityViewModelFactory = MainActivityViewModelFactory(123)
mainActivityViewModel = ViewModelProviders.of(this, mainActivityViewModelFactory)
.get(MainActivityViewModel::class.java)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.tvName.text = mainActivityViewModel.getCurrentCount().toString()
binding.user = user
binding.btnName.setOnClickListener {
binding.tvName.text = mainActivityViewModel.getUpdatedCount().toString()
}
}
private fun displayGreeting() {
binding.apply { tvName.setText("Hello! " + user?.name) }
}
}
You have to add the viewmodel as an observer of the lifecycle of your activity. You need to add this in your Activity
getLifecycle().addObserver(viewModel)
More info here

delay init methods in ViewModel

I have following project in Github : https://github.com/AliRezaeiii/TMDb-Paging
I have to postDelay calling methods in my ViewModel since datasource is not initialized :
abstract class DetailViewModel(private val item: TmdbItem) : BaseViewModel() {
private val handler = Handler(Looper.getMainLooper())
val trailers: ObservableList<Video> = ObservableArrayList()
val isTrailersVisible = ObservableBoolean(false)
private val _cast = MutableLiveData<List<Cast>>()
val cast: LiveData<List<Cast>> = _cast
val isCastVisible = ObservableBoolean(false)
init {
handler.postDelayed({
showTrailers()
showCast()
}, 100)
}
protected abstract fun getTrailers(id: Int): Observable<List<Video>>
protected abstract fun getCast(id: Int): Observable<List<Cast>>
private fun showTrailers() {
EspressoIdlingResource.increment() // App is busy until further notice
compositeDisposable.add(getTrailers(item.id)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doFinally {
if (!EspressoIdlingResource.getIdlingResource().isIdleNow) {
EspressoIdlingResource.decrement() // Set app as idle.
}
}
.subscribe({ videos ->
if (videos.isNotEmpty()) {
isTrailersVisible.set(true)
}
with(trailers) {
clear()
addAll(videos)
}
}
) { throwable -> Timber.e(throwable) })
}
private fun showCast() {
EspressoIdlingResource.increment() // App is busy until further notice
compositeDisposable.add(getCast(item.id)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doFinally {
if (!EspressoIdlingResource.getIdlingResource().isIdleNow) {
EspressoIdlingResource.decrement() // Set app as idle.
}
}
.subscribe({ cast ->
if (cast.isNotEmpty()) {
isCastVisible.set(true)
}
this._cast.postValue(cast)
}
) { throwable -> Timber.e(throwable) })
}
}
And here is my Fragment :
abstract class DetailFragment<T : TmdbItem>
: BaseDaggerFragment(), CastClickCallback {
protected abstract fun getViewModel(): DetailViewModel
protected abstract fun getLayoutId(): Int
protected abstract fun initViewBinding(root: View): ViewDataBinding
protected abstract fun getTmdbItem(): T
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val viewModel = getViewModel()
val root = inflater.inflate(getLayoutId(), container, false)
initViewBinding(root).apply {
setVariable(BR.vm, viewModel)
lifecycleOwner = viewLifecycleOwner
}
with(root) {
with(activity as AppCompatActivity) {
setupActionBar(details_toolbar) {
setDisplayShowTitleEnabled(false)
setDisplayHomeAsUpEnabled(true)
setDisplayShowHomeEnabled(true)
}
}
summary_label.visibleGone(getTmdbItem().overview.trim().isNotEmpty())
// Make the MotionLayout draw behind the status bar
details_motion.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
summary.setOnClickListener {
val maxLine = resources.getInteger(R.integer.max_lines)
summary.maxLines = if (summary.maxLines > maxLine) maxLine else Int.MAX_VALUE
}
viewModel.cast.observe(viewLifecycleOwner, Observer {
it?.apply {
val adapter = CastAdapter(it, this#DetailFragment)
cast_list.apply {
setHasFixedSize(true)
cast_list.adapter = adapter
}
}
})
with(details_rv) {
postDelayed({ scrollTo(0, 0) }, 100)
}
}
return root
}
}
And BaseDaggerFragment :
open class BaseDaggerFragment : DaggerFragment() {
#Inject
lateinit var dataSource: RemoteDataSource
}
Could be any better solution than :
init {
handler.postDelayed({
showTrailers()
showCast()
}, 100)
}
You can lazy initialize like this way
private val users:MutableLiveData<List<Cast>> by lazy {
MutableLiveData().also {
showTrailers()
showCast()
}
}
more details refer ViewModel

Is there a better and simpler way to optimize helper callback and handler code in kotlin?

I am using helper classes with retry logic which is used throughout my app. I was wondering if there is a way I can combine the handler and callback classes into one instead of having 2 different classes one for callback and one for handler. Here's my code as follows:
Retryhandler:
abstract class RetryHandler(private val totalRetries: Int = 0, private val delayMillis : Long = 0) : Handler() {
private var retryCount: Int = 0
fun retry(): Boolean {
return if (retryCount++ < totalRetries) {
if (delayMillis > 0) {
postDelayed({ onRetry(retryCount) }, delayMillis)
} else {
onRetry(retryCount)
true
}
} else false
}
abstract fun onRetry(retryCount: Int)
}
Retrycallback:
abstract class RetryableCallback(totalRetries: Int = 0, delayMillis : Long = 0)
: RetryHandler(totalRetries, delayMillis), MyCallback {
override fun handleTransactionCompleted() {
if (!onCompleted()) {
if (!retry()) {
onFailed(null)
}
}
}
override fun handleTransactionFailed(e: MyException?) {
if (!retry()) {
onFailed(e)
}
}
abstract fun onCompleted(): Boolean
abstract fun onFailed(e: MyException? = null)
}
Here's how I am using them in my code:
private val newCallback = object: RetryableCallback(5, 5000) {
override fun onRetry(retryCount: Int) {
....}
override fun onCompleted(): Boolean {
}
}
Any ideas ?
Well, as long as I don't fully understand the purpose, let's say like this:
abstract class RetriableCallbackHandler(private val totalRetries: Int = 0, private val delayMillis : Long = 0) : Handler(), MyCallback {
private var retryCount: Int = 0
fun retry(): Boolean {
return if (retryCount++ < totalRetries) {
if (delayMillis > 0) {
postDelayed({ onRetry(retryCount) }, delayMillis)
} else {
onRetry(retryCount)
true
}
} else false
}
abstract fun onRetry(retryCount: Int)
override fun handleTransactionCompleted() {
if (!onCompleted()) {
if (!retry()) {
onFailed(null)
}
}
}
override fun handleTransactionFailed(e: MyException?) {
if (!retry()) {
onFailed(e)
}
}
abstract fun onCompleted(): Boolean
abstract fun onFailed(e: MyException? = null)
}

Categories

Resources