ViewPager with FragmentStatePagerAdapter scrolls before closing - android

I have a ViewPager with a FragmentStatePagerAdapter to let users scroll through videos using a VideoView. It works fine, but when you press the back button, the viewpager scrolls to the left and briefly shows the previous ViewView before closing the viewpager activity.
I understand the FragmentStatePagerAdapter will cache the fragments/views for better memory management, but it seems odd to show the precious view before closing. Is this normal, or is there any way to make sure a view is completely hidden when it's not the current pager in focus?
Here's the code for my Adapter. Basically I return one of two fragments that creates a view with that photo or video in it.
inner class MyAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
override fun getCount(): Int = photoInfo.size
override fun getItemPosition(`object`: Any?): Int = super.getItemPosition(`object`)
override fun getItem(position: Int): Fragment {
when (photoInfo[position].type) {
PHOTO -> {
return PhotoFragment.newInstance(photoInfo[position])
}
VIDEO-> {
return VideoFragment.newInstance(photoInfo[position])
}
else -> {
return PhotoFragment.newInstance(photoInfo[position])
}
}
}
}
And the videofragment:
class VideoFragment : Fragment(), AnkoLogger {
internal var photo: String? = null
internal var totalSize: Int? = null
internal var thumbnail: String? = null
var player: SimpleExoPlayer? = null
var simpleExoPlayerView: SimpleExoPlayerView? = null
var error = false
var shouldLoop = true
var autoPlay = true
var proxy: HttpProxyCacheServer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
photo = arguments.getString("photo")
thumbnail = arguments.getString("thumbnail")
totalSize = arguments.getInt("size")
shouldLoop = defaultSharedPreferences.getBoolean("loop_webm_preference", true)
autoPlay = defaultSharedPreferences.getBoolean("autplay_webm_preference", true)
proxy = getProxy(activity)
}
override fun onDestroyView() {
player?.release()
super.onDestroyView()
}
override fun onPause() {
super.onPause()
}
fun checkAndSetVolume() {
val isMuted = defaultSharedPreferences.getBoolean("mute_video", false)
when (isMuted) {
true -> {
simpleExoPlayerView?.findViewById<ImageButton>(R.id.exo_mute)?.imageResource = R.drawable.volume_on
player?.volume = 0f
}
false -> {
simpleExoPlayerView?.findViewById<ImageButton>(R.id.exo_mute)?.imageResource = R.drawable.volume_off
player?.volume = 1f
}
}
}
override fun getUserVisibleHint(): Boolean {
return super.getUserVisibleHint()
}
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
super.setUserVisibleHint(isVisibleToUser)
if (!isVisibleToUser) {
player?.playWhenReady = false
player?.playbackState
player?.seekTo(0)
} else if (isVisible && isVisibleToUser && (proxy?.isCached(photo) == true) && !error) {
checkAndStartAutoplay()
}
}
fun checkAndStartAutoplay() {
checkAndSetVolume()
player?.playWhenReady = autoPlay
player?.playbackState
}
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
simpleExoPlayerView = SimpleExoPlayerView(context)
val mainHandler = Handler()
val bandwidthMeter = DefaultBandwidthMeter()
val videoTrackSelectionFactory = AdaptiveTrackSelection.Factory(bandwidthMeter)
val trackSelector = DefaultTrackSelector(videoTrackSelectionFactory)
player = ExoPlayerFactory.newSimpleInstance(context, trackSelector)
val fl = FrameLayout(context)
simpleExoPlayerView?.player = player
simpleExoPlayerView?.setShutterBackgroundColor(Color.TRANSPARENT)
player?.repeatMode = if (shouldLoop) 1 else 0
player?.addListener(object : Player.DefaultEventListener() {
override fun onPlayerError(error: ExoPlaybackException?) {
val tv = TextView(context)
tv.text = getString(android.R.string.VideoView_error_text_unknown)
tv.textColor = Color.WHITE
tv.textAlignment = TextView.TEXT_ALIGNMENT_CENTER
fl.addView(tv, FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER))
this#VideoFragment.error = true
}
override fun onLoadingChanged(isLoading: Boolean) {
super.onLoadingChanged(isLoading)
if (!isLoading) {
if (this#VideoFragment.isVisible && this#VideoFragment.userVisibleHint) {
checkAndStartAutoplay()
}
}
}
})
val proxyUrl = proxy?.getProxyUrl(photo)
val dataSourceFactory = DefaultDataSourceFactory(context, Util.getUserAgent(context, "Omnichan"), bandwidthMeter)
val videoSource = ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(Uri.parse(proxyUrl))
player?.prepare(videoSource)
fl.addView(simpleExoPlayerView, FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER))
simpleExoPlayerView?.findViewById<ImageButton>(R.id.exo_mute)?.setOnClickListener {
val isMuted = defaultSharedPreferences.getBoolean("mute_video", false)
defaultSharedPreferences.edit().putBoolean("mute_video", !isMuted).apply()
checkAndSetVolume()
}
return fl
}
companion object {
internal fun newInstance(photoInfo: PhotoInfo): VideoFragment {
val f = VideoFragment()
val args = Bundle()
args.putString("photo", photoInfo.photoUrl)
args.putString("thumbnail", photoInfo.thumbnailUrl)
f.arguments = args
return f
}
private var sharedProxy: HttpProxyCacheServer? = null
private fun newProxy(context: Context): HttpProxyCacheServer {
return HttpProxyCacheServer.Builder(context)
.maxCacheSize((1024 * 1024 * 256).toLong()) // 256 Mb for cache
.build()
}
fun getProxy(context: Context): HttpProxyCacheServer {
return sharedProxy ?: newProxy(context)
}
}
}

Related

Jitsi Meet mute audio and video issue

i'm trying to mute everyone in the conference call to prevent trolling/spamming, but the problem is allowed to umute audio and video at anytime even tho i'm setting the options to be muted by default. P.S : if you have any idea that may help me to prevent this issue from going on into the conference call please just write it down.
MeetingUtils.kt
object MeetingUtils {
private var isMuted: Boolean = true
fun startMeeting(context: Context, meetingCode: String) {
val serverUrl = URL(context.getString(R.string.app_server_url))
val defaultOptions = JitsiMeetConferenceOptions.Builder()
.setServerURL(serverUrl)
.setWelcomePageEnabled(false)
.setAudioMuted(isMuted)
.setVideoMuted(true)
.setFeatureFlag("invite.enabled", false)
.setFeatureFlag("live-streaming.enabled", false)
.setFeatureFlag("meeting-name.enabled", false)
.setFeatureFlag("call-integration.enabled", false)
.setFeatureFlag("recording.enabled", false)
.build()
JitsiMeet.setDefaultConferenceOptions(defaultOptions)
val options = JitsiMeetConferenceOptions.Builder()
.setRoom(meetingCode)
.setUserInfo(null)
val sharedPrefData= SharedPrefData(context)
val currentUser = FirebaseAuth.getInstance().currentUser
if (sharedPrefData.getSkip().equals("Skip"))
{
val userInfoBundle = bundleOf(
"displayName" to "User Not Sign in",
"email" to "Please Sign In",
"avatarURL" to R.drawable.ic_account
)
options.setUserInfo(JitsiMeetUserInfo(userInfoBundle))
}
else
{
if (currentUser != null) {
val userInfoBundle = bundleOf(
"displayName" to sharedPrefData.getName(),
"email" to sharedPrefData.getEmail(),
"avatarURL" to sharedPrefData.getImage()
)
options.setUserInfo(JitsiMeetUserInfo(userInfoBundle))
}
val userInfoBundle = bundleOf(
"displayName" to sharedPrefData.getName() ,
"email" to sharedPrefData.getEmail(),
"avatarURL" to "http://graph.facebook.com/${sharedPrefData.getAuthId()}/picture?type=square"
)
options.setUserInfo(JitsiMeetUserInfo(userInfoBundle))
}
JitsiMeetActivity.launch(context, options.build())
}
}
HomeFragment.kt
class HomeFragment : Fragment() {
private var binding: FragmentHomeBinding? = null
private val minMeetingCodeLength = 10
private var currentUser: FirebaseUser? = null
var email:String?=null
var firstName:String?=null
var lastName:String?=null
var profileImage:String?=null
private val viewModel by viewModel<MainViewModel>()
lateinit var auth: FirebaseAuth
private var sharedPrefData: SharedPrefData?=null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
binding=FragmentHomeBinding.inflate(inflater,container,false)
val view = binding!!.root
onCreateMeetingCodeChange()
onCopyMeetingCodeFromClipboardClick()
onShareMeetingCodeClick()
onJoinMeetingClick()
onCreateMeetingClick()
onMeetingToggleChange()
val mAdView: AdView = view.findViewById(R.id.adView)
val adRequest = AdRequest.Builder().build()
mAdView.loadAd(adRequest)
return view
}
companion object{
fun newInstance(text: String?): HomeFragment? {
val f = HomeFragment()
val b = Bundle()
b.putString("msg", text)
f.arguments = b
return f
}
}
private fun onMeetingToggleChange() {
binding?.tgMeeting?.addOnButtonCheckedListener { toggleGroup, checkedId, isChecked ->
if (isChecked) {
when (checkedId) {
R.id.btnToggleJoinMeeting -> {
binding?.groupCreateMeeting?.makeGone()
binding?.groupJoinMeeting?.makeVisible()
}
R.id.btnToggleCreateMeeting -> {
binding?.groupJoinMeeting?.makeGone()
binding?.groupCreateMeeting?.makeVisible()
val meetingCode = generateMeetingCode()
binding?.etCodeCreateMeeting?.setText(meetingCode)
}
}
}
}
}
private fun onCreateMeetingCodeChange() {
binding?.tilCodeCreateMeeting?.etCodeCreateMeeting?.doOnTextChanged { text, start, before, count ->
if (count >= minMeetingCodeLength) binding?.tilCodeCreateMeeting!!.error = null
}
}
private fun generateMeetingCode(): String {
val allowedChars = ('A'..'Z') + ('a'..'z')
return (1..10)
.map { allowedChars.random() }
.joinToString("")
}
private fun onCopyMeetingCodeFromClipboardClick() {
binding?.tilCodeJoinMeeting?.setEndIconOnClickListener {
val clipboardText = activity?.getTextFromClipboard()
if (clipboardText != null) {
binding?.etCodeJoinMeeting?.setText(clipboardText)
activity?.toast(getString(R.string.main_meeting_code_copied))
} else {
activity?.toast(getString(R.string.main_empty_clipboard))
}
}
}
private fun onShareMeetingCodeClick() {
binding?.tilCodeCreateMeeting?.setEndIconOnClickListener {
if (binding?.etCodeCreateMeeting?.text.toString().length >= minMeetingCodeLength) {
binding!!.tilCodeCreateMeeting.error = null
activity?.startShareTextIntent(
getString(R.string.main_share_meeting_code_title),
"Meeting Code: "+binding!!.etCodeCreateMeeting.text.toString()+"\n "+
getString(R.string.profile_share_app_text, activity!!. applicationContext.packageName)
)
} else {
binding!!.tilCodeCreateMeeting.error =
getString(R.string.main_error_meeting_code_length, minMeetingCodeLength)
}
}
}
private fun onJoinMeetingClick() {
binding?.btnJoinMeeting?.setOnClickListener {
if (binding!!.etCodeJoinMeeting.text.toString().length >= minMeetingCodeLength) {
joinMeeting()
} else {
activity?.toast(getString(R.string.main_error_meeting_code_length, minMeetingCodeLength))
}
}
}
private fun joinMeeting() {
activity?.let {
MeetingUtils.startMeeting(
it,
binding?.etCodeJoinMeeting?.text.toString())
} // Start Meeting
viewModel.addMeetingToDb(
Meeting(
binding?.etCodeJoinMeeting?.text.toString(),
System.currentTimeMillis()
)
) // Add meeting to db
}
private fun onCreateMeetingClick() {
binding?.btnCreateMeeting?.setOnClickListener {
if (binding!!.etCodeCreateMeeting.text.toString().length >= minMeetingCodeLength) {
createMeeting()
} else {
activity?.toast(getString(R.string.main_error_meeting_code_length, minMeetingCodeLength))
}
}
}
private fun createMeeting() {
activity?.let {
MeetingUtils.startMeeting(
it,
binding?.etCodeCreateMeeting?.text.toString()
)
} // Start Meeting
viewModel.addMeetingToDb(
Meeting(
binding?.etCodeCreateMeeting?.text.toString(),
System.currentTimeMillis()
)
) // Add meeting to db
}
}

Exo player fast scroll playing video sound mixed

I am using exoplayer for playing videos .And for this we are used Fragment instance with pagerstateadapter and viewpager2.
But when scroll fast previous played video sound listen in background as well as in screen video means mix the sound in same video player.
Please help me how to solve this.
1.State adapter
class StoriesPagerAdapter(
fragment: Fragment,
val onClick1: VideoItemAdapter.OnItemClicked?,
val onlikeClick: VideoItemAdapter.OnLikeCLicked?,
val onFollowClick: VideoItemAdapter.OnFollowCLicked?,
val ontrendingClick: VideoItemAdapter.OnTrendCLicked?,
val oniconCLick: VideoItemAdapter.OnIconClick?) : FragmentStateAdapter(fragment) {
val dataList:MutableList<Gettrendingvideos.Data.Postlist>=mutableListOf()
override fun getItemCount(): Int {
return dataList.size
}
fun addAll(movies: MutableList<Gettrendingvideos.Data.Postlist>) {
for (movie in movies) {
add(movie)
}
}
fun add(moive: Gettrendingvideos.Data.Postlist) {
dataList.add(moive)
notifyItemInserted(dataList.size - 1)
}
override fun createFragment(position: Int): Fragment {
return StoryViewFragment.newInstance(
onClick1,
onlikeClick,
onFollowClick,
ontrendingClick,
oniconCLick,
dataList[position]
)
}}
2 Fragment
class StoryViewFragment : Fragment(), CommentFragment.onCommentCountIncrease {
private var storyUrl: String? = null
private var storiesDataModel: Gettrendingvideos.Data.Postlist? = null
lateinit var mView: View
private var simplePlayer: SimpleExoPlayer? = null
private var cacheDataSourceFactory: CacheDataSourceFactory? = null
private val simpleCache = MainApplication.simpleCache
private var toPlayVideoPosition: Int = -1
lateinit var viewModel: MainViewModel
lateinit var preferences: SecurePreferences
private var bool: Boolean? = false
var onItemClick: VideoItemAdapter.OnItemClicked? = null
var onlikeCLicked: VideoItemAdapter.OnLikeCLicked? = null
var onFollowCLicked: VideoItemAdapter.OnFollowCLicked? = null
var onTrendCLicked: VideoItemAdapter.OnTrendCLicked? = null
var onIconClick: VideoItemAdapter.OnIconClick? = null
lateinit var huserId: String
lateinit var token: String
companion object {
fun newInstance(
itemClicked: VideoItemAdapter.OnItemClicked?,
likeCLicked: VideoItemAdapter.OnLikeCLicked?,
onFollowCLicked: VideoItemAdapter.OnFollowCLicked?,
onTrendCLicked: VideoItemAdapter.OnTrendCLicked?,
onIconClick: VideoItemAdapter.OnIconClick?,
storiesDataModel: Gettrendingvideos.Data.Postlist
) = StoryViewFragment()
.apply {
arguments = Bundle().apply {
putParcelable(Constants.KEY_STORY_DATA, storiesDataModel)
}
this.onItemClick = itemClicked
this.onlikeCLicked = likeCLicked
this.onFollowCLicked = onFollowCLicked
this.onTrendCLicked = onTrendCLicked
this.onIconClick = onIconClick
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout for this fragment
mView = inflater.inflate(
R.layout.layout_main,
container,
false
)
return mView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProviders.of(this, ViewModelFactory(RetrofitBuilder.apiService))
.get(MainViewModel::class.java)
preferences =
SecurePreferences(
requireActivity(),
AppConstants.preferenceName,
AppConstants.USER_DETAILS,
true
)
storiesDataModel = arguments?.getParcelable(Constants.KEY_STORY_DATA)
setData()
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
if (!preferences.getString(AppConstants.USER_ID).equals(null)) {
huserId = preferences.getString(AppConstants.USER_ID)!!
Log.d("TAG", "onActivityCreated: $huserId")
}
}
#SuppressLint("SetTextI18n")
private fun setData() {
Log.d("TAG", "setData: $storiesDataModel")
mView.textview2.text = storiesDataModel?.user_name
mView.like_count.text = storiesDataModel?.total_likes.toString()
comment_count.text = storiesDataModel?.total_comments.toString()
mView.textview.text = storiesDataModel?.type
Glide.with(this).load(storiesDataModel?.user_profile_pic).placeholder(R.drawable.profile).into(mView.image)
if (storiesDataModel?.is_like == 0) {
mView.imageView4.setImageResource(R.drawable.ic_like)
} else {
mView.imageView4.setImageResource(R.drawable.ic_like_red)
}
if (storiesDataModel?.is_following!! == 0) {
mView.textview3.text = "Follow"
} else {
mView.textview3.text = "Following"
}
if (storiesDataModel?.user_id.toString()==preferences.getString(AppConstants.USER_ID)) {
mView.textview3.visibility = View.GONE
}
image.setOnClickListener {
if (preferences.getString(AppConstants.token).equals(null)) {
MainActivity().show(childFragmentManager, "")
} else {
preferences.put(
AppConstants.OtherProfile_UserId,
storiesDataModel?.user_id.toString()
)
}
}
val simplePlayer = getPlayer()
player_view_story.player = simplePlayer player_view_story.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FILL)
simplePlayer?.setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING)
storyUrl = storiesDataModel?.video_url
prepareMedia(storiesDataModel)
}
override fun onPause() {
pauseVideo()
super.onPause()
}
override fun onResume() {
restartVideo()
super.onResume()
}
override fun onDestroy() {
releasePlayer()
super.onDestroy()
}
private fun pausePlayer() {
simplePlayer?.setPlayWhenReady(false)
simplePlayer?.getPlaybackState()
}
private fun startPlayer() {
simplePlayer?.setPlayWhenReady(true)
simplePlayer?.getPlaybackState()
}
private val playerCallback: Player.EventListener? = object : Player.EventListener {
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
}
override fun onPlayerError(error: com.google.android.exoplayer2.ExoPlaybackException?) {
super.onPlayerError(error)
}
}
private fun prepareVideoPlayer() {
simplePlayer = ExoPlayerFactory.newSimpleInstance(context)
cacheDataSourceFactory = CacheDataSourceFactory(
simpleCache,
DefaultHttpDataSourceFactory(
Util.getUserAgent(
context,
"exo"
)
)
)
}
private fun getPlayer(): SimpleExoPlayer? {
if (simplePlayer == null) {
prepareVideoPlayer()
}
return simplePlayer
}
private fun prepareMedia(datamodel: Gettrendingvideos.Data.Postlist?{
val uri = Uri.parse(datamodel?.video_url)
simplePlayer.repeatMode = Player.REPEAT_MODE_ONE
simplePlayer.playWhenReady = true
if (storiesDataModel!!.type == "following") {
following_page.typeface = Typeface.DEFAULT_BOLD
trending_page.setTypeface(null, Typeface.NORMAL)
} else {
following_page.setTypeface(null, Typeface.BOLD)
}
if (storiesDataModel.type == "treading") {
trending_page.typeface = Typeface.DEFAULT_BOLD
following_page.setTypeface(null, Typeface.NORMAL)
} else {
trending_page.setTypeface(null, Typeface.BOLD)
}
if (simplePlayer.playWhenReady == true) {
}
simplePlayer.addListener(playerCallback)
toPlayVideoPosition = -1
}
private fun setArtwork(drawable: Drawable, playerView: PlayerView) {
playerView.useArtwork = true
playerView.defaultArtwork = drawable
}
private fun playVideo() {
simplePlayer.playWhenReady = true
}
private fun restartVideo() {
if (simplePlayer == null) {
prepareMedia(storiesDataModel)
} else {
simplePlayer.seekToDefaultPosition()
simplePlayer.playWhenReady = true
}
}
private fun pauseVideo() {
simplePlayer.playWhenReady = false
}
private fun releasePlayer() {
simplePlayer.stop(true)
simplePlayer.release()
}}
override fun setMenuVisibility(menuVisible: Boolean) {
if (!menuVisible){
simplePlayer?.playWhenReady = false
simplePlayer?.pause()
}
super.setMenuVisibility(menuVisible)
}
JUST ADD THIS IN YOUR StoryViewFragment.

RecyclerView not binding data notifyDataSetChanged not working when filter data

I have two screens first one has recycler view list of data and searchView above it that's filter data in this recycler, the view Model code of the first fragment
class MscInspectionViewModel(val activity: LaunchActivity, val mRootView: MscInspectFragment) :
BaseViewModel(),
SwipeRefreshLayout.OnRefreshListener {
val toolBarTitle: MutableLiveData<String> = MutableLiveData()
private val getDataError = MutableLiveData<Boolean>()
var listType = MutableLiveData<Int>()
val hint = MutableLiveData<String>()
private var isRefreshing: Boolean = false
private var mSharedPreferences: SharedPreferences? = null
val dataListAdapter = ContainersUnderCheckAdapter(activity)
val backClickListener = View.OnClickListener { activity.supportFragmentManager.popBackStack() }
val filterDataByTab = object : TabLayout.OnTabSelectedListener {
override fun onTabReselected(tab: TabLayout.Tab?) {
}
override fun onTabUnselected(tab: TabLayout.Tab?) {
}
override fun onTabSelected(tab: TabLayout.Tab?) {
when (tab!!.text) {
activity.resources.getString(R.string.cidPending) -> {
listType.value = 0
getPendingData()
}
activity.resources.getString(R.string.cidDone) -> {
listType.value = 1
getDoneData()
}
}
}
}
val filterData = object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
if (query.length > 2) {
val mQuery = Utility(activity).switchArabicNumerals(query)
dataListAdapter.getFilter(3, listType.value!!).filter(mQuery)
} else {
errorMessage.value = activity.resources.getString(R.string.addCorrectNumber)
}
return true
}
override fun onQueryTextChange(newText: String): Boolean {
if (newText.length > 2) {
val mQuery = Utility(activity).switchArabicNumerals(newText)
dataListAdapter.getFilter(3, listType.value!!).filter(mQuery)
}
return false;
}
}
val closeImgListener = View.OnClickListener {
mRootView.svSearchMSC.setQuery("", true)
if (listType.value == 1) {
dataListAdapter.getFilter(1, listType.value!!).filter("ANY")
} else if (listType.value == 0) {
dataListAdapter.getFilter(2, listType.value!!).filter("PENDING")
}
}
init {
listType.value = 0
mSharedPreferences = getDefaultSharedPreferences(activity.applicationContext)
toolBarTitle.value = activity.resources.getString(R.string.mscInspectTitle)
hint.value = activity.resources.getString(R.string.msc_search)
getData()
}
fun getData() {
onRetrievePostListStart()
subscription = apiAccount.getContainersUnderCheck(
"getContainersUnderCheck",
mSharedPreferences!!.getString(Constants.CFID, "")!!,
mSharedPreferences!!.getString(Constants.CFTOKEN, "")!!
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe {}
.doOnTerminate {}
.subscribe({ result ->
result?.let {
if (result.ResponseCode != null && result.ResponseCode.trim() != "000") {
onRetrievePostListError(result.ResponseMessage)
} else {
result.ContainersData?.let { it1 -> onRetrievePostListSuccess(it1) }
}
}
}, { throwable ->
android.util.Log.e("getDataInquiry", throwable.message!!)
onRetrievePostListError(activity.resources.getString(R.string.general_error))
})
}
private fun getPendingData() {
val query = mRootView.svSearchMSC.query.toString()
if (query == "") {
dataListAdapter.getFilter(2, listType.value!!).filter("PENDING")
} else {
if (query.length > 2) {
dataListAdapter.getFilter(3, listType.value!!).filter(query)
} else {
errorMessage.value = activity.resources.getString(R.string.addCorrectNumber)
}
}
}
private fun getDoneData() {
val query = mRootView.svSearchMSC.query.toString()
if (query == "") {
dataListAdapter.getFilter(1, listType.value!!).filter("ANY")
} else {
if (query.length > 2) {
dataListAdapter.getFilter(3, listType.value!!).filter(query)
} else {
errorMessage.value = activity.resources.getString(R.string.addCorrectNumber)
}
}
}
private fun onRetrievePostListStart() {
loading.value = true
}
private fun onRetrievePostListFinish() {
loading.value = false
isRefreshing = false
}
private fun onRetrievePostListSuccess(containersData: List<ContainersData>) {
onRetrievePostListFinish()
dataListAdapter.updateInquiryAdapter(containersData as ArrayList<ContainersData>)
if (listType.value == 1) {
dataListAdapter.getFilter(1, listType.value!!).filter("ANY")
} else if (listType.value == 0) {
dataListAdapter.getFilter(2, listType.value!!).filter("PENDING")
}
}
private fun onRetrievePostListError(message: String?) {
onRetrievePostListFinish()
getDataError.value = true
errorMessage.value = message
}
override fun onCleared() {
super.onCleared()
subscription.dispose()
}
override fun onRefresh() {
isRefreshing = true
getData()
}
}
adapter is :
class ContainersUnderCheckAdapter(val activity: LaunchActivity) :
RecyclerView.Adapter<ContainersUnderCheckAdapter.ViewHolder>() {
private lateinit var mDataSet: ArrayList<ContainersData>
private lateinit var mDataSetFiltered: ArrayList<ContainersData>
fun updateInquiryAdapter(dataSet: ArrayList<ContainersData>) {
mDataSet = ArrayList()
mDataSet.clear()
mDataSet.addAll(dataSet)
mDataSetFiltered = mDataSet
getFilter(2, 1).filter("PENDING")
// notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding: ContianerItemFieldLayoutBinding = DataBindingUtil
.inflate(
LayoutInflater.from(parent.context),
R.layout.contianer_item_field_layout,
parent,
false
)
return ViewHolder(binding, activity)
}
override fun getItemCount(): Int {
return if (::mDataSetFiltered.isInitialized) mDataSetFiltered.size else 0
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(mDataSetFiltered[position])
}
operator fun get(position: Int): ContainersData {
return mDataSetFiltered.get(position)
}
/**
* #filterType :
* IF 1 : filter on Data Type RJCTD + APPROVED
* 2 : filter on Data Type PENDING
* 3 :
*/
fun getFilter(filterType: Int, listType: Int): Filter {
return object : Filter() {
override fun performFiltering(charSequence: CharSequence): FilterResults {
val charString = charSequence.toString()
mDataSetFiltered = if (charString.isEmpty()) {
mDataSet
} else {
val filteredList = ArrayList<ContainersData>()
for (row in mDataSet) {
when (filterType) {
1 -> {
if (row.status == "RJCTD" || row.status == "APPROVED") {
filteredList.add(row)
}
}
2 -> {
if (row.status == charString) {
filteredList.add(row)
}
}
3 -> {
when (listType) {
0 -> {
if ((row.CID!!.contains(charString.toUpperCase(Locale.ROOT)) || row.TN!!.contains(
charSequence
) || row.PN!!.contains(charSequence)) && row.status == "PENDING"
) {
filteredList.add(row)
}
}
1 -> {
if ((row.CID!!.contains(charString.toUpperCase(Locale.ROOT)) || row.TN!!.contains(
charSequence
) || row.PN!!.contains(charSequence)) && row.status != "PENDING"
) {
filteredList.add(row)
}
}
}
}
}
}
filteredList
}
val filterResults = FilterResults()
filterResults.values = mDataSetFiltered
return filterResults
}
override fun publishResults(
charSequence: CharSequence,
filterResults: FilterResults
) {
if (::mDataSetFiltered.isInitialized) {
mDataSetFiltered = try {
filterResults.values as ArrayList<ContainersData>
} catch (e: Exception) {
Log.e("mDataSetFiltered",e.message!!)
ArrayList()
}
when (filterType) {
1->{
mDataSetFiltered.sortWith(Comparator { p0, p1 -> p1!!.UpdateDate.compareTo(p0!!.UpdateDate) })
}
2->{
mDataSetFiltered.sortWith(Comparator { p0, p1 -> p0!!.ID!!.compareTo(p1.ID!!) })
}
}
}
// refresh the list with filtered data
notifyDataSetChanged()
}
}
}
class ViewHolder(
private val binding: ContianerItemFieldLayoutBinding,
val activity: LaunchActivity
) : RecyclerView.ViewHolder(binding.root) {
private val viewModel = MscInspectionListViewModel(activity)
fun bind(data: ContainersData) {
viewModel.bind(data)
binding.viewModel = viewModel
}
}
}
any data in this recycler on click go to fragment has tow recycler first one to show data, the second one to pick Images
the second-page code
class MSCDataFragment : Fragment() {
lateinit var rootView: View
lateinit var activity: LaunchActivity
lateinit var utility: Utility
lateinit var loadingView: LoadingView
private lateinit var viewModel: MSCDataViewModel
private lateinit var binding: FragmentMscdataBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (getActivity() != null) {
activity = getActivity() as LaunchActivity
utility = Utility(activity)
loadingView = LoadingView(activity)
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_mscdata, container, false)
rootView = binding.root
initial()
return rootView
}
private fun initial() {
viewModel = ViewModelProvider(
this, ViewModelFactory(
activity,
arguments!!.getSerializable("Data") as ContainersData
)
).get(MSCDataViewModel::class.java)
binding.viewModel = viewModel
// binding.imgList.layoutManager = GridLayoutManager(activity, 3)
binding.containerInfo.layoutManager = LinearLayoutManager(activity)
binding.openCIDNotValid.typeface =
Typeface.createFromAsset(activity.assets, "Bahij_Janna-Regular.ttf")
binding.openCIDNotValid.setOnCheckedChangeListener(viewModel.onOpenCidNotValidListener)
viewModel.loading.observe(this, Observer { loading ->
loading?.let {
if (it) {
loadingView.show()
} else {
loadingView.dismiss()
}
}
})
viewModel.errorMessage.observe(this, Observer { msg ->
msg?.let {
utility.ShowToast(msg)
}
})
viewModel.imagesAdapters2.observe(this, Observer { msg ->
msg?.let {
binding.imgList.apply {
layoutManager = GridLayoutManager(activity, 3)
adapter = it
}
}
})
rootView.toolbar_Back.setOnClickListener(viewModel.backClickListener)
binding.btnAddImages.setOnClickListener(viewModel.pickImages)
binding.successContianer.setOnClickListener(viewModel.correctContainer)
binding.damagedContianer.setOnClickListener(viewModel.wrongContainer)
}
}
the view model is :
class MSCDataViewModel(val activity: LaunchActivity, val containersData: ContainersData) :
BaseViewModel(), GetImagesListener {
#Inject
lateinit var restApiAccount: RestApiAccount
val toolBarTitle: MutableLiveData<String> = MutableLiveData()
val ButtonText: MutableLiveData<String> = MutableLiveData()
var openCIDNotValidVisibility = MutableLiveData<Int>()
private val getDataError = MutableLiveData<Boolean>()
val btnImagesVisibility = MutableLiveData<Int>()
var imgeNoteVisibility = MutableLiveData<Int>()
var successVisibility = MutableLiveData<Int>()
var damagedVisibility = MutableLiveData<Int>()
var notesVisibility = MutableLiveData<Int>()
val btnVisibility = MutableLiveData<Int>()
var canNotOpen = MutableLiveData<Int>()
private val images = ArrayList<Image>()
var utility = Utility(activity)
private var CURRENTINDEX = 0
private var mSharedPreferences: SharedPreferences? = null
val DataListAdapter = ContainerDataAdapter(activity)
var imagesAdapter = ContainerImagesAdapter(activity, containersData.status!!, ArrayList())
val imagesAdapters2 = MutableLiveData<ContainerImagesAdapter2>()
val userInfo: UserInfo
val backClickListener = View.OnClickListener { activity.supportFragmentManager.popBackStack() }
val pickImages = View.OnClickListener {
pickImages()
}
val correctContainer = View.OnClickListener {}
val onOpenCidNotValidListener =
CompoundButton.OnCheckedChangeListener { buttonView, isChecked ->
if (isChecked) {
successVisibility.value = View.GONE
canNotOpen.value = 1
} else {
canNotOpen.value = 0
successVisibility.value = View.VISIBLE
}
}
val wrongContainer = View.OnClickListener {}
var mscNotes: ObservableField<String> = ObservableField("")
init {
canNotOpen.value = 0
mSharedPreferences =
PreferenceManager.getDefaultSharedPreferences(activity.applicationContext)
toolBarTitle.value = containersData.CID
ButtonText.value = activity.resources.getString(R.string.cleanContianer)
userInfo = utility.readObjectFromSharedPreferences(
mSharedPreferences,
Constants.USER_INFO_KEY,
UserInfo::class.java
) as UserInfo
openCIDNotValidVisibility.value = View.GONE
fillData()
}
private fun fillData() {
val data: LinkedHashMap<String, String> = containersData.data!!
val captionsMap = utility.readObjectFromSharedPreferences(
mSharedPreferences, Constants.CAPTIONS_MAP_KEY,
HashMap::class.java
) as HashMap<String, String>
if (containersData.data.size > 0) {
val list = ArrayList<KeyValueModel>()
for (inside in data.keys) {
val ky = captionsMap[inside]
val value = data[inside].toString()
ky?.let { KeyValueModel(it, value) }?.let { list.add(it) }
}
DataListAdapter.updateInquiryAdapter(list)
} else {
errorMessage.value = activity.resources.getString(R.string.no_data)
}
if (containersData.ImageList != null && containersData.ImageList.isNotEmpty()) {
imagesAdapter.updateContainerImagesAdapter(containersData.ImageList)
}
}
private fun pickImages() {
activity.setCallBack(this)
val pictureDialog: AlertDialog
val builder = activity.let { AlertDialog.Builder(it) }
val dialogView = View.inflate(activity, R.layout.choose_camera_method, null)
builder.setView(dialogView)
val nafithPopupContainer = dialogView.findViewById<RelativeLayout>(R.id.RLTitle)
nafithPopupContainer.setBackgroundColor(
ContextCompat.getColor(
activity,
R.color.mainColor
)
)
val popUpGallery = dialogView.findViewById<LinearLayout>(R.id.PopupGellary)
val popUpCamera = dialogView.findViewById<LinearLayout>(R.id.PopupCamera)
pictureDialog = builder.create()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Objects.requireNonNull<Window>(pictureDialog.window)
.setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
} else {
if (pictureDialog.window != null) {
pictureDialog.window!!.setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
}
}
popUpGallery.setOnClickListener {
fromGallery()
pictureDialog.dismiss()
}
popUpCamera.setOnClickListener {
fromCamera()
pictureDialog.dismiss()
}
val popupClose = dialogView.findViewById<ImageView>(R.id.popupClose)
popupClose.setOnClickListener { pictureDialog.dismiss() }
pictureDialog.show()
}
private fun fromGallery() {
ImagePicker.create(activity)
.toolbarImageTitle(activity.resources.getString(R.string.get_image))
.toolbarArrowColor(ContextCompat.getColor(activity, R.color.colorWhite))
.showCamera(false)
.limit(6)
.start()
}
private fun fromCamera() {
ImagePicker.cameraOnly().start(activity)
}
override fun onGetImage(image: Image) {
imgeNoteVisibility.value = View.GONE
imagesAdapter.updateContainerImagesAdapter(image)
images.add(image)
}
override fun addingImagesDone(mImages: MutableList<Image>) {
images.clear()
images.addAll(mImages)
imgeNoteVisibility.value = View.GONE
val listString :ArrayList<String> = ArrayList()
for (i in mImages.indices){
listString.add(mImages[i].path)
}
imagesAdapters2.value = ContainerImagesAdapter2(activity,containersData.status!!,listString)
imagesAdapters2.value!!.notifyItemRangeChanged(0,listString.size)
}
override fun onImgDelete(image: String) {
var x = 0
try {
for (i in 0 until images.size) {
x = i
if (images[i].path == image) {
images.remove(images[i])
}
}
} catch (e: Exception) {
Log.e("errorImages", e.message!!)
Log.e("xx", x.toString())
}
}
private fun onRetrievePostListStart() {
loading.value = true
}
private fun onRetrievePostListFinish() {
loading.value = false
}
private fun onRetrievePostListSuccess(msg: String?) {
onRetrievePostListFinish()
}
private fun onRetrievePostListError(message: String?) {
onRetrievePostListFinish()
getDataError.value = true
errorMessage.value = message
}
}
Adapter code is :
class ContainerImagesAdapter2() : RecyclerView.Adapter<ContainerImagesAdapter2.ViewHolder>() {
var status: String = ""
lateinit var activity: LaunchActivity
lateinit var utility: Utility
constructor(
mActivity: LaunchActivity,
mStatus: String,
pathsList: ArrayList<String>
) : this() {
activity = mActivity
pathsDataSet = pathsList
status = mStatus
utility = Utility(activity)
}
private var pathsDataSet: ArrayList<String> = ArrayList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding: ContianerImageFieldBinding = DataBindingUtil
.inflate(
LayoutInflater.from(parent.context),
R.layout.contianer_image_field,
parent,
false
)
return ViewHolder(binding, activity)
}
override fun getItemCount(): Int {
return pathsDataSet.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bindPath(pathsDataSet[position], position)
}
inner class ViewHolder(
private val binding: ContianerImageFieldBinding,
val activity: LaunchActivity
) : RecyclerView.ViewHolder(binding.root) {
private val viewModel = MscImagesListViewModel(activity)
fun bindPath(data: String, position: Int) {
viewModel.bindPath(data)
binding.viewModel = viewModel
if (status != "PENDING") {
binding.closeImg.visibility = View.GONE
}
binding.closeImg.setOnClickListener {}
binding.mainImg.setOnClickListener {
val fragment = FullImageFragment()
val bundle = Bundle()
val list = ArrayList<String>()
for (item in 0 until pathsDataSet.size) {
list.add(pathsDataSet[item])
}
bundle.putSerializable("ImageList", list)
bundle.putInt("Position", position)
fragment.arguments = bundle
activity.supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, fragment).addToBackStack(fragment.tag)
.commit()
}
}
}
}
if you filter data using search view in the first-page and pick images in the second page , list of picked images doesn't appear, if you going to the second page without filtering data everything ok
solve Problem found
Just Update constraint-layout library in gradle dependencies to version '2.0.0-beta4'

Blank screen with RecyclerView No adapter attached

I'm tying to parse JSON in recyclerview. App compiles fine but it's outputting empty/blank screen
BlogAdapter.kt
class BlogAdapter(private val blogList: List<Blog>) : RecyclerView.Adapter<BlogAdapter.ViewHolder>() {
override fun getItemCount()= blogList.size
private var mContext: Context? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
this.mContext=parent.context;
return ViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.character_item,
parent,
false
)
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val mBlog = this.blogList[position]
if (mBlog.img != null) {
Glide.with(mContext!!)
.load(mBlog.img)
.into(holder.ivThumbnail)
}
if (mBlog.name != null) {
holder.tvTitle.text = mBlog.name
println("Log: Kabe "+mBlog.name)
}
}
class ViewHolder(itemView:View):RecyclerView.ViewHolder(itemView){
val ivThumbnail:ImageView = itemView.findViewById(R.id.ivThumbnail);
val tvTitle:TextView = itemView.findViewById(R.id.tvTitle);
}
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
var mainViewModel: MainViewModel? = null
var mBlogAdapter: BlogAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
getPopularBlog()
swipe_refresh.setOnRefreshListener { getPopularBlog() }
}
private fun getPopularBlog() {
swipe_refresh.isRefreshing = false
mainViewModel!!.allBlog.observe(this, Observer { charactersList ->
prepareRecyclerView(charactersList)
})
}
private fun prepareRecyclerView(blogList: List<Blog>) {
mBlogAdapter = BlogAdapter(blogList)
if (this.resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
blogRecyclerView.layoutManager = LinearLayoutManager(this)
} else {
blogRecyclerView.layoutManager = GridLayoutManager(this, 4)
}
blogRecyclerView.itemAnimator = DefaultItemAnimator()
blogRecyclerView.adapter = mBlogAdapter
}
}
My Json file looks like this:
[
{
"id": 1,
"name": "potter",
"img": "https://images.example.com/potter.jpg"
},
{ …}
]
I've created it based on this tutorial: https://itnext.io/kotlin-wrapping-your-head-around-livedata-mutablelivedata-coroutine-networking-and-viewmodel-b552c3a74eec
Any suggestions please
EDIT:
class BlogRepository() {
private var character = mutableListOf<ABCCharacters>()
private var mutableLiveData = MutableLiveData<List<ABCCharacters>>()
val completableJob = Job()
private val coroutineScope = CoroutineScope(Dispatchers.IO + completableJob)
private val thisApiCorService by lazy {
RestApiService.createCorService()
}
fun getMutableLiveData():MutableLiveData<List<ABCCharacters>> {
coroutineScope.launch {
val request = thisApiCorService.getPopularBlog()
withContext(Dispatchers.Main) {
try {
val response = request.await()
val mBlogWrapper = response;
if (/*mBlogWrapper != null &&*/ mBlogWrapper.isNotEmpty()) {
character = mBlogWrapper as MutableList<ABCCharacters>
mutableLiveData.value = character
}
} catch (e: HttpException) {
// Log exception //
} catch (e: Throwable) {
// Log error //)
}
}
}
return mutableLiveData;
}
}
You forget to call notifyDataSetChanged, when you setup your RecyclerView widget. Below the full method call, to make it works.
private fun prepareRecyclerView(blogList: List<Blog>) {
mBlogAdapter = BlogAdapter(blogList)
if (this.resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
blogRecyclerView.layoutManager = LinearLayoutManager(this)
} else {
blogRecyclerView.layoutManager = GridLayoutManager(this, 4)
}
blogRecyclerView.itemAnimator = DefaultItemAnimator()
blogRecyclerView.adapter = mBlogAdapter
mBlogAdapter.notifyDataSetChanged()
}
Try using below implementation:
class MainActivity : AppCompatActivity() {
lateinit var mainViewModel: MainViewModel
var mBlogAdapter: BlogAdapter? = null
var blogList: List<Blog> = arrayListOf()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
// init your RV here
prepareRecyclerView()
getPopularBlog()
swipe_refresh.setOnRefreshListener { mainViewModel.getAllBlog() }
}
private fun getPopularBlog() {
swipe_refresh.isRefreshing = false
mainViewModel.getAllBlog().observe(this, Observer { charactersList ->
blogList = charactersList
mBlogAdapter?.notifyDataSetChanged()
})
}
private fun prepareRecyclerView() {
mBlogAdapter = BlogAdapter(blogList)
if (this.resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
blogRecyclerView.layoutManager = LinearLayoutManager(this)
} else {
blogRecyclerView.layoutManager = GridLayoutManager(this, 4)
}
blogRecyclerView.itemAnimator = DefaultItemAnimator()
blogRecyclerView.adapter = mBlogAdapter
}
}
Modify your view model like below:
class MainViewModel() : ViewModel() {
val characterRepository= BlogRepository()
fun getAllBlog(): MutableLiveData<List<ABCCharacters>> {
return characterRepository.getMutableLiveData()
}
override fun onCleared() {
super.onCleared()
characterRepository.completableJob.cancel()
}
}

I want that when I press hardware back button in SongPlayingFragment I should return to main screen. How can I do it?

package com.shivamkapila.echo.fragments
import android.app.Activity
import android.content.Context
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.media.AudioManager
import android.media.MediaPlayer
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.support.v4.app.Fragment
import android.support.v4.content.ContextCompat
import android.util.Log
import android.view.*
import android.widget.ImageButton
import android.widget.SeekBar
import android.widget.TextView
import android.widget.Toast
import com.cleveroad.audiovisualization.AudioVisualization
import com.cleveroad.audiovisualization.DbmHandler
import com.cleveroad.audiovisualization.GLAudioVisualizationView
import com.shivamkapila.echo.CurrentSongHelper
import com.shivamkapila.echo.R
import com.shivamkapila.echo.Songs
import com.shivamkapila.echo.activities.MainActivity
import com.shivamkapila.echo.databases.EchoDatabase
import com.shivamkapila.echo.utils.SeekBarController
import java.util.*
import java.util.concurrent.TimeUnit
class SongPlayingFragment : Fragment() {
object Statified {
var myActivity: Activity? = null
var mediaPlayer: MediaPlayer? = null
var startTimeNext: TextView? = null
var endTimeNext: TextView? = null
var playPauseImageButton: ImageButton? = null
var previousImageButton: ImageButton? = null
var nextImageButton: ImageButton? = null
var loopImageButton: ImageButton? = null
var seekbar: SeekBar? = null
var songArtistView: TextView? = null
var songTitleView: TextView? = null
var shuffleImageButton: ImageButton? = null
var check: Boolean = true
var _currentPosition: Int = 0
var fetchSongs: ArrayList<Songs>? = null
var currentSongHelper: CurrentSongHelper? = null
var audioVisualization: AudioVisualization? = null
var glView: GLAudioVisualizationView? = null
var fab: ImageButton? = null
var favoriteContent: EchoDatabase? = null
var counter: Int = 0
var mSensorManager: SensorManager? = null
var mSensorListener: SensorEventListener? = null
var MY_PREFS_NAME = "ShakeFeature"
var back: String? = null
var updateSongTime = object : Runnable {
override fun run() {
try {
val getCurrent = Statified.mediaPlayer?.getCurrentPosition()
startTimeNext?.setText(String.format("%02d:%02d",
TimeUnit.MILLISECONDS.toMinutes(getCurrent?.toLong() as Long),
TimeUnit.MILLISECONDS.toSeconds(getCurrent?.toLong() as Long) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(getCurrent?.toLong() as Long))))
seekbar?.setProgress(getCurrent?.toInt() as Int)
Statified.check = true
Handler().postDelayed(this, 1000)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
object Staticated {
var MY_PREFS_SHUFFLE = "Shuffle feature"
var MY_PREFS_LOOP = "Loop feature"
fun onSongComplete() {
if (Statified.currentSongHelper?.isShuffle as Boolean) {
playNext("PlayNextLikeNormalShuffle")
Statified.currentSongHelper?.isPlaying = true
} else {
if (Statified.currentSongHelper?.isLoop as Boolean) {
Statified.currentSongHelper?.isPlaying = true
var nextSong = Statified.fetchSongs?.get(Statified._currentPosition)
Statified.currentSongHelper?.songPath = nextSong?.songData
Statified.currentSongHelper?.songTitle = nextSong?.songTitle
Statified.currentSongHelper?.songArtist = nextSong?.artist
Statified.currentSongHelper?.songId = nextSong?.songID as Long
Statified.currentSongHelper?.currentPosition = Statified._currentPosition
updateTextViews(Statified.currentSongHelper?.songTitle as String, Statified.currentSongHelper?.songArtist as String)
Statified.mediaPlayer?.reset()
try {
Statified.mediaPlayer?.setDataSource(Statified.myActivity, Uri.parse(Statified.currentSongHelper?.songPath) as Uri)
Statified.mediaPlayer?.prepare()
Statified.mediaPlayer?.start()
processInformation(Statified.mediaPlayer as MediaPlayer)
} catch (e: Exception) {
e.printStackTrace()
}
} else {
playNext("PlayNextNormal")
Statified.currentSongHelper?.isPlaying = true
}
}
if (Statified.favoriteContent?.checkifIdExists(Statified.currentSongHelper?.songId?.toInt() as Int) as Boolean) {
Statified.fab?.setImageDrawable(ContextCompat.getDrawable(Statified.myActivity, R.drawable.favorite_on))
} else {
Statified.fab?.setImageDrawable(ContextCompat.getDrawable(Statified.myActivity, R.drawable.favorite_off))
}
}
fun updateTextViews(songTitle: String, songArtist: String) {
var songTitleUpdated = songTitle
var songArtistUpdated = songArtist
if (songTitle.equals("<unknown>", true)) {
songTitleUpdated = "unknown"
}
if (songArtist.equals("<unknown>", true)) {
songArtistUpdated = "unknown"
}
Statified.songTitleView?.setText(songTitleUpdated)
Statified.songArtistView?.setText(songArtistUpdated)
}
fun processInformation(mediaPlayer: MediaPlayer) {
val finalTime = mediaPlayer.duration
val startTime = mediaPlayer.currentPosition
Statified.seekbar?.max = finalTime
Statified.startTimeNext?.setText(String.format("%02d:%02d",
TimeUnit.MILLISECONDS.toMinutes(startTime.toLong()),
TimeUnit.MILLISECONDS.toSeconds(startTime.toLong()) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(startTime.toLong()))))
Statified.endTimeNext?.setText(String.format("%02d:%02d",
TimeUnit.MILLISECONDS.toMinutes(finalTime.toLong()),
TimeUnit.MILLISECONDS.toSeconds(finalTime.toLong()) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(finalTime.toLong()))))
Statified.seekbar?.setProgress(startTime)
Handler().postDelayed(Statified.updateSongTime, 1000)
}
fun playNext(check: String) {
if (check.equals("PlayNextNormal", true)) {
Statified._currentPosition = Statified._currentPosition + 1
} else if (check.equals("PlayNextLikeNormalShuffle", true)) {
var randomObject = Random()
var randomPosition = randomObject.nextInt(Statified.fetchSongs?.size?.plus(1) as Int)
Statified._currentPosition = randomPosition
}
if (Statified._currentPosition == Statified.fetchSongs?.size) {
Statified._currentPosition = 0
}
Statified.currentSongHelper?.isLoop = false
var nextSong = Statified.fetchSongs?.get(Statified._currentPosition)
Statified.currentSongHelper?.songPath = nextSong?.songData
Statified.currentSongHelper?.songTitle = nextSong?.songTitle
Statified.currentSongHelper?.songArtist = nextSong?.artist
Statified.currentSongHelper?.songId = nextSong?.songID as Long
Statified.currentSongHelper?.currentPosition = Statified._currentPosition
var editorLoop = Statified.myActivity?.getSharedPreferences(Staticated.MY_PREFS_LOOP, Context.MODE_PRIVATE)?.edit()
Statified.currentSongHelper?.isLoop = false
Statified.loopImageButton?.setBackgroundResource(R.drawable.loop_white_icon)
editorLoop?.putBoolean("feature", false)
editorLoop?.apply()
if (Statified.currentSongHelper?.isPlaying as Boolean) {
Statified.playPauseImageButton?.setBackgroundResource(R.drawable.pause_icon)
} else {
Statified.playPauseImageButton?.setBackgroundResource(R.drawable.play_icon)
}
updateTextViews(Statified.currentSongHelper?.songTitle as String, Statified.currentSongHelper?.songArtist as String)
Statified.mediaPlayer?.reset()
try {
Statified.mediaPlayer?.setDataSource(Statified.myActivity, Uri.parse(Statified.currentSongHelper?.songPath) as Uri)
Statified.mediaPlayer?.prepare()
Statified.mediaPlayer?.start()
Staticated.processInformation(Statified.mediaPlayer as MediaPlayer)
processInformation(Statified.mediaPlayer as MediaPlayer)
} catch (e: Exception) {
e.printStackTrace()
}
if (Statified.favoriteContent?.checkifIdExists(Statified.currentSongHelper?.songId?.toInt() as Int) as Boolean) {
Statified.fab?.setImageDrawable(ContextCompat.getDrawable(Statified.myActivity, R.drawable.favorite_on))
} else {
Statified.fab?.setImageDrawable(ContextCompat.getDrawable(Statified.myActivity, R.drawable.favorite_off))
}
}
fun playPrevious() {
Statified._currentPosition = Statified._currentPosition - 1
if (Statified._currentPosition == -1) {
Statified._currentPosition = 0
}
if (Statified.currentSongHelper?.isPlaying as Boolean) {
Statified.playPauseImageButton?.setBackgroundResource(R.drawable.pause_icon)
} else {
Statified.playPauseImageButton?.setBackgroundResource(R.drawable.play_icon)
}
Statified.currentSongHelper?.isLoop = false
var nextSong = Statified.fetchSongs?.get(Statified._currentPosition)
Statified.currentSongHelper?.songPath = nextSong?.songData
Statified.currentSongHelper?.songTitle = nextSong?.songTitle
Statified.currentSongHelper?.songArtist = nextSong?.artist
Statified.currentSongHelper?.songId = nextSong?.songID as Long
Statified.currentSongHelper?.currentPosition = Statified._currentPosition
Staticated.updateTextViews(Statified.currentSongHelper?.songTitle as String, Statified.currentSongHelper?.songArtist as String)
Statified.mediaPlayer?.reset()
try {
Statified.mediaPlayer?.setDataSource(Statified.myActivity, Uri.parse(Statified.currentSongHelper?.songPath) as Uri)
Statified.mediaPlayer?.prepare()
Statified.mediaPlayer?.start()
Staticated.processInformation(Statified.mediaPlayer as MediaPlayer)
processInformation(Statified.mediaPlayer as MediaPlayer)
} catch (e: Exception) {
e.printStackTrace()
}
if (Statified.favoriteContent?.checkifIdExists(Statified.currentSongHelper?.songId?.toInt() as Int) as Boolean) {
Statified.fab?.setImageDrawable(ContextCompat.getDrawable(Statified.myActivity, R.drawable.favorite_on))
} else {
Statified.fab?.setImageDrawable(ContextCompat.getDrawable(Statified.myActivity, R.drawable.favorite_off))
}
}
}
var mAcceleration: Float = 0f
var mAccelerationCurrent: Float = 0f
var mAccelerationLast: Float = 0f
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
val view = inflater!!.inflate(R.layout.fragment_song_playing, container, false)
setHasOptionsMenu(true)
activity.title = "Now Playing"
Statified.seekbar = view?.findViewById(R.id.seekBar)
Statified.startTimeNext = view?.findViewById(R.id.startTime)
Statified.endTimeNext = view?.findViewById(R.id.endTime)
Statified.playPauseImageButton = view?.findViewById(R.id.playPauseButton)
Statified.nextImageButton = view?.findViewById(R.id.nextButton)
Statified.previousImageButton = view?.findViewById(R.id.previousButton)
Statified.loopImageButton = view?.findViewById(R.id.loopButton)
Statified.shuffleImageButton = view?.findViewById(R.id.shuffleButton)
Statified.songArtistView = view?.findViewById(R.id.songArtist)
Statified.songTitleView = view?.findViewById(R.id.songTitle)
Statified.glView = view?.findViewById(R.id.visualizer_view)
Statified.fab = view?.findViewById(R.id.favoriteIcon)
Statified.fab?.alpha = 0.8f
return view
}
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Statified.audioVisualization = Statified.glView as AudioVisualization
}
override fun onAttach(context: Context?) {
super.onAttach(context)
Statified.myActivity = context as Activity
}
override fun onAttach(activity: Activity?) {
super.onAttach(activity)
Statified.myActivity = activity
}
override fun onResume() {
super.onResume()
Statified.audioVisualization?.onResume()
Statified.mSensorManager?.registerListener(Statified.mSensorListener, Statified.mSensorManager?.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL)
}
override fun onPause() {
Statified.audioVisualization?.onPause()
Statified.mSensorManager?.unregisterListener(Statified.mSensorListener)
super.onPause()
}
override fun onDestroyView() {
super.onDestroyView()
Statified.audioVisualization?.release()
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
Statified.currentSongHelper = CurrentSongHelper()
Statified.currentSongHelper?.isPlaying = true
Statified.currentSongHelper?.isLoop = false
Statified.currentSongHelper?.isShuffle = false
Statified.favoriteContent = EchoDatabase(Statified.myActivity)
var path: String? = null
var _songTitle: String? = null
var _songArtist: String? = null
var songId: Long = 0
var fromFavBottomBar: String? = null
var fromMainScreenBottomBar: String? = null
try {
path = arguments.getString("path")
_songTitle = arguments.getString("songTitle")
_songArtist = arguments.getString("songArtist")
songId = arguments.getInt("songId").toLong()
Statified._currentPosition = arguments.getInt("songPosition")
Statified.fetchSongs = arguments.getParcelableArrayList("songData")
Statified.currentSongHelper?.songPath = path
Statified.currentSongHelper?.songTitle = _songTitle
Statified.currentSongHelper?.songArtist = _songArtist
Statified.currentSongHelper?.songId = songId
Statified.currentSongHelper?.currentPosition = Statified._currentPosition
fromFavBottomBar = arguments.get("FavBottomBar") as? String
fromMainScreenBottomBar = arguments.get("MainScreenBottomBar") as? String
Staticated.updateTextViews(Statified.currentSongHelper?.songTitle as String, Statified.currentSongHelper?.songArtist as String)
} catch (e: Exception) {
e.printStackTrace()
}
if (fromFavBottomBar != null) {
Statified.mediaPlayer = FavoriteFragment.Statified.mediaPlayer
Staticated.processInformation(Statified.mediaPlayer as MediaPlayer)
} else if (fromMainScreenBottomBar != null) {
Statified.mediaPlayer = MainScreenFragment.Statified.mediaPlayer
Staticated.processInformation(Statified.mediaPlayer as MediaPlayer)
} else {
Statified.mediaPlayer = MediaPlayer()
Statified.mediaPlayer?.setAudioStreamType(AudioManager.STREAM_MUSIC)
try {
Statified.mediaPlayer?.setDataSource(Statified.myActivity, Uri.parse(path) as Uri)
Statified.mediaPlayer?.prepare()
} catch (e: Exception) {
e.printStackTrace()
}
Statified.mediaPlayer?.start()
Staticated.processInformation(Statified.mediaPlayer as MediaPlayer)
}
Staticated.processInformation(Statified.mediaPlayer as MediaPlayer)
if (Statified.mediaPlayer?.isPlaying as Boolean) {
Statified.playPauseImageButton?.setBackgroundResource(R.drawable.pause_icon)
} else {
Statified.playPauseImageButton?.setBackgroundResource(R.drawable.play_icon)
}
Statified.mediaPlayer?.setOnCompletionListener {
Staticated.onSongComplete()
}
clickHandler()
var visualizationHandler = DbmHandler.Factory.newVisualizerHandler(Statified.myActivity as Context, 0)
Statified.audioVisualization?.linkTo(visualizationHandler)
var prefsForShuffle = Statified.myActivity?.getSharedPreferences(Staticated.MY_PREFS_SHUFFLE, Context.MODE_PRIVATE)
var isShuffleAllowed = prefsForShuffle?.getBoolean("feature", false)
if (isShuffleAllowed as Boolean) {
Statified.currentSongHelper?.isShuffle = true
Statified.currentSongHelper?.isLoop = false
Statified.shuffleImageButton?.setBackgroundResource(R.drawable.shuffle_icon)
Statified.loopImageButton?.setBackgroundResource(R.drawable.loop_white_icon)
} else {
Statified.currentSongHelper?.isShuffle = false
Statified.shuffleImageButton?.setBackgroundResource(R.drawable.shuffle_white_icon)
}
var prefsForLoop = Statified.myActivity?.getSharedPreferences(Staticated.MY_PREFS_LOOP, Context.MODE_PRIVATE)
var isLoopAllowed = prefsForLoop?.getBoolean("feature", false)
if (isLoopAllowed as Boolean) {
Statified.currentSongHelper?.isShuffle = false
Statified.currentSongHelper?.isLoop = true
Statified.shuffleImageButton?.setBackgroundResource(R.drawable.shuffle_white_icon)
Statified.loopImageButton?.setBackgroundResource(R.drawable.loop_icon)
} else {
Statified.currentSongHelper?.isLoop = false
Statified.loopImageButton?.setBackgroundResource(R.drawable.loop_white_icon)
}
if (Statified.favoriteContent?.checkifIdExists(Statified.currentSongHelper?.songId?.toInt() as Int) as Boolean) {
Statified.fab?.setImageDrawable(ContextCompat.getDrawable(Statified.myActivity, R.drawable.favorite_on))
} else {
Statified.fab?.setImageDrawable(ContextCompat.getDrawable(Statified.myActivity, R.drawable.favorite_off))
}
seekbarHandler()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Statified.mSensorManager = Statified.myActivity?.getSystemService(Context.SENSOR_SERVICE) as SensorManager
mAcceleration = 0.0f
mAccelerationCurrent = SensorManager.GRAVITY_EARTH
mAccelerationLast = SensorManager.GRAVITY_EARTH
bindShakeListener()
}
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
menu?.clear()
inflater?.inflate(R.menu.song_playing_menu, menu)
super.onCreateOptionsMenu(menu, inflater)
}
override fun onPrepareOptionsMenu(menu: Menu?) {
super.onPrepareOptionsMenu(menu)
val item: MenuItem? = menu?.findItem(R.id.action_redirect)
item?.isVisible = true
val item2: MenuItem? = menu?.findItem(R.id.action_sort)
item2?.isVisible = false
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item?.itemId) {
R.id.action_redirect -> {
var pos = 0
if (Statified.back.equals("Favorite", true)) {
pos = 0
}
if (Statified.back.equals("MainScreen", true)) {
pos = 1
}
if (pos == 1) {
val mainScreenFragment = MainScreenFragment()
(context as MainActivity).supportFragmentManager
.beginTransaction()
.replace(R.id.details_fragment, mainScreenFragment)
.commit()
}
if (pos == 0) {
val favoriteFragment = FavoriteFragment()
(context as MainActivity).supportFragmentManager
.beginTransaction()
.replace(R.id.details_fragment, favoriteFragment)
.commit()
}
return false
}
}
return false
}
fun clickHandler() {
Statified.fab?.setOnClickListener({
if (Statified.favoriteContent?.checkifIdExists(Statified.currentSongHelper?.songId?.toInt() as Int) as Boolean) {
Statified.fab?.setImageDrawable(ContextCompat.getDrawable(Statified.myActivity, R.drawable.favorite_off))
Statified.favoriteContent?.deleteFavourite(Statified.currentSongHelper?.songId?.toInt() as Int)
Toast.makeText(Statified.myActivity, "Removed from favorites", Toast.LENGTH_SHORT).show()
} else {
Statified.fab?.setImageDrawable(ContextCompat.getDrawable(Statified.myActivity, R.drawable.favorite_on))
Statified.favoriteContent?.storeAsFavorite(Statified.currentSongHelper?.songId?.toInt(), Statified.currentSongHelper?.songArtist,
Statified.currentSongHelper?.songTitle, Statified.currentSongHelper?.songPath)
Toast.makeText(Statified.myActivity, "Added to Favorites", Toast.LENGTH_SHORT).show()
}
})
Statified.shuffleImageButton?.setOnClickListener({
var editorShuffle = Statified.myActivity?.getSharedPreferences(Staticated.MY_PREFS_SHUFFLE, Context.MODE_PRIVATE)?.edit()
var editorLoop = Statified.myActivity?.getSharedPreferences(Staticated.MY_PREFS_LOOP, Context.MODE_PRIVATE)?.edit()
if (Statified.currentSongHelper?.isShuffle as Boolean) {
Statified.currentSongHelper?.isShuffle = false
Statified.shuffleImageButton?.setBackgroundResource(R.drawable.shuffle_white_icon)
editorShuffle?.putBoolean("feature", false)
editorShuffle?.apply()
} else {
Statified.currentSongHelper?.isLoop = false
Statified.currentSongHelper?.isShuffle = true
Statified.loopImageButton?.setBackgroundResource(R.drawable.loop_white_icon)
Statified.shuffleImageButton?.setBackgroundResource(R.drawable.shuffle_icon)
editorShuffle?.putBoolean("feature", true)
editorShuffle?.apply()
editorLoop?.putBoolean("feature", false)
editorLoop?.apply()
}
})
Statified.nextImageButton?.setOnClickListener({
Statified.currentSongHelper?.isPlaying = true
if (Statified.currentSongHelper?.isLoop as Boolean) {
Statified.loopImageButton?.setBackgroundResource(R.drawable.loop_white_icon)
}
if (Statified.currentSongHelper?.isShuffle as Boolean) {
Staticated.playNext("PlayNextLikeNormalShuffle")
} else {
Staticated.playNext("PlayNextNormal")
}
})
Statified.previousImageButton?.setOnClickListener({
Statified.currentSongHelper?.isPlaying = true
if (Statified.currentSongHelper?.isLoop as Boolean) {
Statified.loopImageButton?.setBackgroundResource(R.drawable.loop_white_icon)
}
Staticated.playPrevious()
})
Statified.loopImageButton?.setOnClickListener({
var editorShuffle = Statified.myActivity?.getSharedPreferences(Staticated.MY_PREFS_SHUFFLE, Context.MODE_PRIVATE)?.edit()
var editorLoop = Statified.myActivity?.getSharedPreferences(Staticated.MY_PREFS_LOOP, Context.MODE_PRIVATE)?.edit()
if (Statified.currentSongHelper?.isLoop as Boolean) {
Statified.currentSongHelper?.isLoop = false
Statified.loopImageButton?.setBackgroundResource(R.drawable.loop_white_icon)
editorLoop?.putBoolean("feature", false)
editorLoop?.apply()
} else {
Statified.currentSongHelper?.isLoop = true
Statified.currentSongHelper?.isShuffle = false
Statified.loopImageButton?.setBackgroundResource(R.drawable.loop_icon)
Statified.shuffleImageButton?.setBackgroundResource(R.drawable.shuffle_white_icon)
editorLoop?.putBoolean("feature", true)
editorLoop?.apply()
editorShuffle?.putBoolean("feature", false)
editorShuffle?.apply()
}
})
Statified.playPauseImageButton?.setOnClickListener({
if (Statified.mediaPlayer?.isPlaying as Boolean) {
Statified.mediaPlayer?.pause()
Statified.currentSongHelper?.isPlaying = false
Statified.playPauseImageButton?.setBackgroundResource(R.drawable.play_icon)
} else {
Statified.mediaPlayer?.start()
Statified.currentSongHelper?.isPlaying = true
Statified.playPauseImageButton?.setBackgroundResource(R.drawable.pause_icon)
Staticated.processInformation(Statified.mediaPlayer as MediaPlayer)
}
})
}
fun bindShakeListener() {
Statified.mSensorListener = object : SensorEventListener {
override fun onAccuracyChanged(p0: Sensor?, p1: Int) {
}
override fun onSensorChanged(p0: SensorEvent) {
val x = p0.values[0]
val y = p0.values[1]
val z = p0.values[2]
mAccelerationLast = mAccelerationCurrent
mAccelerationCurrent = Math.sqrt(((x * x + y * y + z * z).toDouble())).toFloat()
val delta = mAccelerationCurrent - mAccelerationLast
mAcceleration = mAcceleration * 0.9f + delta
if (mAcceleration > 12) {
println("11111")
val prefs = Statified.myActivity?.getSharedPreferences(Statified.MY_PREFS_NAME, Context.MODE_PRIVATE)
val isAllowed = prefs?.getBoolean("feature", false)
if (isAllowed as Boolean && Statified.check == true) {
Statified.currentSongHelper?.isPlaying = true
if (Statified.currentSongHelper?.isLoop as Boolean) {
Statified.loopImageButton?.setBackgroundResource(R.drawable.loop_white_icon)
}
if (Statified.currentSongHelper?.isShuffle as Boolean) {
Staticated.playNext("PlayNextLikeNormalShuffle")
} else {
Staticated.playNext("PlayNextNormal")
}
Statified.check = false
}
}
}
}
}
fun seekbarHandler() {
val seekbarListener = SeekBarController()
Statified.seekbar?.setOnSeekBarChangeListener(seekbarListener)
}
Let try this ,
This is java code Just u can convert to kotlin it will work fine.
In your Activity
Declare a static variable
public static boolean IS_MUSIC_SCREEN = false;
Implement this method
#Override
public void onBackPressed() {
if (IS_MUSIC_SCREEN) {
IS_MUSIC_SCREEN=false;
startActivity(new Activity(this,MainActivity.class));
}else{
super.onBackPressed();
}
}
In your Fragment,
IS_MUSIC_SCREEN is true set in onCreateView
Like this ,
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_song_playing, container, false);
MainActivity.IS_MUSIC_SCREEN =true;
return view;
}
A simple approach would be to initialise a BackHandler mechanism with the Fragment. I have such an approach with my BaseFragment class that would return a boolean to true if the back action is to be handled by the fragment instead of activity. For this you can have a custom LifecycleAdapter:
interface LifecycleAdapter {
fun onBackPressed() : Boolean = false
// add other methods like onActivityResult or similar
// if needed that is to be delegated to the fragment
}
Now in the BaseActivity you would have 2 functions one for addingFragment and a register function for MutableList<WeakReference<LifecycleAdapter>>
open class BaseActivity : AppCompatActivity() { // which ever type
protected open val lifecycleReferrals : MutableList<WeakReference<LifecycleAdapter>> = mutableListOf()
fun addFragment(fragment: BaseFragment,
#IdRes containerId: Int = R.id.fragment_container,
replace: Boolean = true,
addToBackstack: Boolean = false) {
supportFragmentManager?.beginTransaction()?.run {
if (addToBackstack){
addToBackStack(fragment.javaClass.simpleName)
}
if (replace) {
replace(containerId, fragment) // add tag when needed
} else {
add(containerId, fragment)
}
registerLifecycleReferrals(fragment)
commit()
}
}
fun registerLifecycleReferrals(adapter: LifecycleAdapter){
lifecycleReferrals.add(WeakReference(adapter))
}
override fun onBackPressed() {
if (lifecycleReferrals.none { it.get()?.onBackPressed(0) == true }) {
super.onBackPressed()
}
}
}
when ever you need a any class accessing the controller methods like onBackPressed() you can implement the interface in the required class and call registerLifecycleReferrals(obj) from the activity.
Now your base fragment class would be:
open class BaseFragment : Fragment(), LifecycleAdapter{
// have parent level constructs and implementation
// that would serve you well across the entire project
}
and your current fragment can be:
class SongPlayingFragment : BaseFragment() {
// do all fragment inits and override methods
override fun onBackPressed(): Boolean {
if (Statified.currentSongHelper?.isPlaying == true) {
// handle the call and switch to MainScreenActivity
context?.apply {
startActivity<MainScreenActivity>() // anko extension
return true
}
}
return super.onBackPressed()
}
}
Note: The adapters are weak referenced in the BaseActivity class because if the Fragment undergoes a destruction process it can be easily freed up by the GC and list wouldn't withhold the reference to it.

Categories

Resources