How to open a "Details" Fragment onclick of Recyclerview in Kotlin - android

I have home fragment and I want it to go to another fragment which will show its "details", which passes the data of the clicked recyclerview item to that "details" fragment.
When I click the article it will move to detail article which passes the data.
As for the code, here's the adapter:
class ArticleAdapter(private val articleList: ArrayList<Article>) :
RecyclerView.Adapter<ArticleAdapter.MyViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val binding = ItemArticleBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return MyViewHolder(binding)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val data = articleList[position]
holder.bind(data)
}
class MyViewHolder(private val binding: ItemArticleBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(data: Article) {
Glide.with(binding.root.context)
.load(data.img)
.into(binding.articleImage)
binding.articleTitle.text = data.title
binding.root.setOnClickListener {
val article = Article(
data.title,
data.img,
data.content
)
}
}
}
override fun getItemCount(): Int {
return articleList.size
}
}
Here's my detailFragment
class DetailArticleFragment : Fragment() {
private var _binding: FragmentDetailArticleBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentDetailArticleBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val intent = Intent(binding.root.context, DetailArticleFragment::class.java)
val article = intent.getParcelableExtra<Article>(DETAIL_ARTICLE) as Article
Glide.with(this)
.load(article.img)
.into(_binding!!.articleImage)
_binding!!.articleTitle.text = article.title
_binding!!.articleDescription.text = article.content
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
companion object {
const val DETAIL_ARTICLE = "detail_article"
}
}

You need to pass click listener interface to adapter, for example:
typealias OnArticleClick = (article: Article) -> Unit
class ArticleAdapter(
private val articleList: ArrayList<Article>
) :
RecyclerView.Adapter<ArticleAdapter.MyViewHolder>() {
var onArticleClick: OnArticleClick? = null
...
binding.root.setOnClickListener {
val article = Article(
data.title,
data.img,
data.content
)
onArticleClick?.invoke(article)
}
...
}
And init onArticleClick in your home fragment with RecyclerView:
adapter.apply {
onArticleClick = {
// show details fragment
}
}

Related

Arraylist loop unexpectedly on kotlin recycleview

Here is when the list increase
I call data from API and place it in recycleview horizontal and vertical, but when I try to move on Profile Menu with bottom navigation and back again on Home Menu where my horizontal and vertical recycleview is, the data on recycleview start to increase, it only happen for vertical recycleview
Here is my code:
SectionPagerAdapter for vertical recycleview
class SectionsPagerAdapter(fm: FragmentManager) :
FragmentPagerAdapter(
fm
) {
var new_craft: ArrayList<Data>? = ArrayList()
var popular: ArrayList<Data>? = ArrayList()
var recommended: ArrayList<Data>? = ArrayList()
override fun getItem(position: Int): Fragment {
var fragment : Fragment
return when (position) {
0 -> {
fragment = HomeNewCraftFragment()
val bundle = Bundle()
bundle.putParcelableArrayList("data", new_craft)
fragment.setArguments(bundle)
return fragment
}
1 -> {
fragment = HomePopularFragment()
val bundle = Bundle()
bundle.putParcelableArrayList("data", popular)
fragment.setArguments(bundle)
return fragment
}
2 -> {
fragment = HomeRecommendedFragment()
val bundle = Bundle()
bundle.putParcelableArrayList("data", recommended)
fragment.setArguments(bundle)
return fragment
}
else -> {
fragment = HomeNewCraftFragment()
val bundle = Bundle()
bundle.putParcelableArrayList("data", new_craft)
fragment.setArguments(bundle)
return fragment
}
}
}
override fun getPageTitle(position: Int): CharSequence? {
return when (position) {
0 -> "New Craft"
1 -> "Popular"
2 -> "Recommended"
else -> null
}
}
override fun getCount(): Int {
return 3
}
fun setData(newStateListParms: ArrayList<Data>?, popularListParms: ArrayList<Data>?, recomendedListParms: ArrayList<Data>?) {
new_craft = newStateListParms
popular = popularListParms
recommended = recomendedListParms
}
}
Home Fragment:
class HomeFragment : Fragment(), HomeAdapter.ItemAdapterCallback, HomeContract.View {
private var adapter: HomeAdapter? = null
var progressDialog: Dialog? = null
private var newStateList: ArrayList<Data>? = ArrayList()
private var popularList: ArrayList<Data>? = ArrayList()
private var recomendedList: ArrayList<Data>? = ArrayList()
private lateinit var presenter: HomePresenter
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_home, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
initView()
presenter = HomePresenter(this)
presenter.getHome()
}
private fun initView() {
progressDialog = Dialog(requireContext())
val dialogLayout = layoutInflater.inflate(R.layout.dialog_loader, null)
progressDialog?.let {
it.setContentView(dialogLayout)
it.setCancelable(false)
it.window?.setBackgroundDrawableResource(android.R.color.transparent)
}
var user = IcaCraft.getApp().getUser()
var userResponse = Gson().fromJson(user, User::class.java)
if (!userResponse.profile_photo_url.isNullOrEmpty()) {
Glide.with(requireActivity())
.load(userResponse.profile_photo_url)
.into(ivProfile)
}
}
override fun onClick(v: View?, data: Data) {
var bundle = Bundle()
bundle.putParcelable("data", data)
val detail = Intent(activity, DetailActivity::class.java).putExtras(bundle)
startActivity(detail)
}
override fun onHomeSuccess(homeResponse: HomeResponse) {
for (a in homeResponse.data.indices) {
var items: List<String> = homeResponse.data[a].types?.split(",") ?: ArrayList()
for (x in items.indices)
{
if (items[x].equals("new_craft", true)) {
newStateList?.add(homeResponse.data[a])
} else if (items[x].equals("recommended", true)) {
recomendedList?.add(homeResponse.data[a])
} else if (items[x].equals("popular", true)) {
popularList?.add(homeResponse.data[a])
}
}
}
adapter = HomeAdapter(homeResponse.data, this)
val layoutManager: RecyclerView.LayoutManager =
LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
rvList.layoutManager = layoutManager
rvList.adapter = adapter
val sectionsPagerAdapter = SectionsPagerAdapter(
childFragmentManager
)
sectionsPagerAdapter.setData(newStateList, popularList, recomendedList)
viewPager.adapter = sectionsPagerAdapter
tabLayout.setupWithViewPager(viewPager)
}
override fun onHomeFailed(message: String) {
Toast.makeText(activity, message, Toast.LENGTH_LONG).show()
}
override fun showLoading() {
progressDialog?.show()
}
override fun dismissLoading() {
progressDialog?.dismiss()
}
}
HomeCraftAdapter: adapter for vertical recycleview
class HomeNewCraftAdapter (
private val listData: ArrayList<Data>,
private val itemAdapterCallback: ItemAdapterCallback
) : RecyclerView.Adapter<HomeNewCraftAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val view = layoutInflater.inflate(R.layout.item_home_vertical, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(listData[position], itemAdapterCallback)
}
override fun getItemCount(): Int {
return listData.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(data : Data, itemAdapterCallback : ItemAdapterCallback) {
itemView.apply {
tvTitle.text = data.name
tvPrice.formatPrice(data?.price.toString())
rbCraft.rating = data.rate?.toFloat() ?: 0f
Glide.with(context)
.load(data.picturePath)
.into(ivPoster)
itemView.setOnClickListener { view -> itemAdapterCallback.onClick(view, data) }
}
}
}
interface ItemAdapterCallback {
fun onClick(v: View?, data:Data)
}
}
And HomeNewCraftFragment : for vertical recycleview fragment
class HomeNewCraftFragment : Fragment() , HomeNewCraftAdapter.ItemAdapterCallback {
private var adapter: HomeNewCraftAdapter? = null
private var newcraftlist: ArrayList<Data>? = ArrayList()
private var test: String? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_home_new_craft, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
newcraftlist = arguments?.getParcelableArrayList("data")
adapter = HomeNewCraftAdapter(newcraftlist!!, this)
val layoutManager: RecyclerView.LayoutManager = LinearLayoutManager(activity)
rcListNewCraft.layoutManager = layoutManager
rcListNewCraft.adapter = adapter
}
override fun onClick(v: View?, data: Data) {
val detail = Intent(activity, DetailActivity::class.java).putExtra("data", data)
startActivity(detail)
}
}
When you leave from your HomeFragment and coming back again, your HomeFragment keeps the old newStateList and add same values in it again. So, you need to empty the values before adding new values.
override fun onHomeSuccess(homeResponse: HomeResponse) {
newStateList = ArrayList() // empty it before load it again.
for (a in homeResponse.data.indices) {
You might need to empty the recomendedList and popularList as well.

Recyclerview not showing items Kotlin

My App is just shows an Empty Screen and RecyclerView is not showing anything or is not working but there are no compile time or run time errors.
It would be great help if I get an answer ...
I have been making an app that uses a RecyclerView but it's not showing any thing..why contents of the recycler view have not been showing up.my codes are bellow
Here is My FeedFragment, Adapter
//Fragment
#AndroidEntryPoint
class FeedFragment : Fragment(R.layout.feed_fragment) {
private var _binding: FeedFragmentBinding? = null
private val binding get() = _binding!!
private lateinit var feedAdapter: FeedAdapter
private val viewModel: FeedViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FeedFragmentBinding.inflate(inflater, container, false)
val view = binding.root
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupRv()
getCharacters()
}
private fun getCharacters() {
viewModel.listData.observe(viewLifecycleOwner, Observer { pagingData ->
feedAdapter.submitData(viewLifecycleOwner.lifecycle, pagingData)
})
}
private fun setupRv() {
feedAdapter = FeedAdapter()
binding.feedRv.layoutManager =
LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
binding.feedRv.apply {
adapter = feedAdapter
setHasFixedSize(true)
visibility = View.VISIBLE
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
//PagingDataAdapter
class FeedAdapter : PagingDataAdapter<Characters,FeedAdapter.FeedViewHolder >(DiffCallback()) {
inner class FeedViewHolder(private val binding: FeedFragmentRvBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(characters: Characters) {
with(binding) {
Glide.with(itemView)
.load(characters.image)
.transition(DrawableTransitionOptions.withCrossFade())
.error(R.drawable.ic_launcher_background)
.into(feedRvImage)
feedRvName.text = characters.name
feedRvStatus.text = characters.status
feedRvSpecies.text = characters.species
feedRvGender.text = characters.gender
println(characters.name)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FeedViewHolder {
val binding =
FeedFragmentRvBinding.inflate(LayoutInflater.from(parent.context),parent,false)
return FeedViewHolder(binding)
}
override fun onBindViewHolder(holder: FeedViewHolder, position: Int) {
getItem(position)?.let { holder.bind(it) }
}
class DiffCallback : DiffUtil.ItemCallback<Characters>() {
override fun areItemsTheSame(oldItem: Characters, newItem: Characters): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Characters, newItem: Characters): Boolean {
return oldItem == newItem
}
}
}
// retrofit response
Update your CharacterResponse model class to parse data accordingly.
data class CharacterResponse(
val info: Info,
val results: List<Characters>
)

RecyclerView doesn't load data initially

I made an app from which I get data from TMDB API, everything seems to work but when I start the app, it displays only hint text, after scrolling the View get's updated with the data from the API
This is how it looks before scrolling
And this is how it looks after scrolling down a a bit
This is how I implemented it:
HomeFragment.kt
class HomeFragment : Fragment() {
private var _binding: FragmentHomeBinding? = null
private lateinit var popularMovies: RecyclerView
private lateinit var popularMoviesAdapter: MoviesAdapter
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val homeViewModel = ViewModelProvider(this)[HomeViewModel::class.java]
_binding = FragmentHomeBinding.inflate(inflater, container, false)
popularMovies = binding.popularMovies
popularMovies.layoutManager = LinearLayoutManager(context,LinearLayoutManager.VERTICAL,false)
popularMoviesAdapter = MoviesAdapter(listOf())
popularMovies.addItemDecoration(DividerItemDecoration(context,DividerItemDecoration.VERTICAL))
popularMovies.adapter = popularMoviesAdapter
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
MoviesRepository.getPopularMovies(page = 1,onSuccess = ::onPopularMoviesFetched,onError = ::onError)
}
private fun onPopularMoviesFetched(movies: List<Movie>) {
popularMoviesAdapter.updateMovies(movies)
}
private fun onError() {
Toast.makeText(context, getString(R.string.error_fetch_movies), Toast.LENGTH_SHORT).show()
}
MovieAdapter.kt
class MoviesAdapter(
private var movies: List<Movie>
) : RecyclerView.Adapter<MoviesAdapter.MovieViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder {
val view = LayoutInflater
.from(parent.context)
val binding = MovieItemBinding.inflate(view)
return MovieViewHolder(binding)
}
override fun getItemCount(): Int = movies.size
override fun onBindViewHolder(holder: MovieViewHolder, position: Int) {
holder.bind(movies[position])
}
fun updateMovies(movies: List<Movie>) {
this.movies = movies
notifyDataSetChanged()
}
inner class MovieViewHolder(private val binding: MovieItemBinding) : RecyclerView.ViewHolder(binding.root) {
private val poster: ImageView = itemView.findViewById(R.id.item_movie_poster)
fun bind(movie: Movie) {
binding.movieTitle.text =movie.title
binding.movieReleaseDate.text = movie.releaseDate
binding.movieOverview.text = movie.overview
binding.movieReleaseDate.text = movie.releaseDate
Glide.with(itemView)
.load("https://image.tmdb.org/t/p/w342${movie.posterPath}")
.transform(CenterCrop())
.into(poster)
}
}
make adapter initialization on onViewCreated instead of onCreateView

Data not refreshing on fragment recreation in ViewPager2 PagedList DiffUtil FragmentStateAdapter

I was trying to display Two sets of Product List in ViewPager tabs inside a fragment. I was also using Paging library. Able to get data loaded and pagination is also working fine. I was also able to invalidate and reload paged list data, if I am in same fragment.
On moving to another fragment from this Tab layout and return to this fragment. I am able to see old data in both the tabs. But reload/pagination is not happening. Afer Invalidating the data, the fetched new data is not shown. The recycler view contains old data. I am getting the data from API and execute submit list - Diff Utils is also getting called. But the ProductPagedListAdapter - recycler view methods are not called.
I feel on recreating the fragment adapter is recreating but it is not getting bound to existing recycler view. I tried retainInstance, it was not working. I am using the two different instances of same ProductFragment in view pager. Due to some issues I am observing data from Parent Fragment ProductTabFragment and sending data to ViewPager fragments.
Any help on this would be highly appreciated.
ViewPager Fragment
class ProductTabFragment : Fragment() {
private lateinit var tabLayout: TabLayout
private lateinit var viewPager: ViewPager2
#Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
private val viewModel: ProductViewModel by viewModels(
ownerProducer = { activity as FragmentActivity },
factoryProducer = { viewModelFactory }
)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.product_tab_fragment, container, false)
tabLayout = view.findViewById(R.id.tabLayoutProduct)
viewPager = view.findViewById(R.id.viewPagerLayoutProduct)
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewPager.apply {
adapter = ProductAdapter(childFragmentManager, viewLifecycleOwner.lifecycle, viewModel.getTabCount())
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
viewModel.selectedTab = position
}
})
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = when (position) {
POSITION_TAB_RECOMMENDED -> TAB_TITLE_RECOMMENDED
POSITION_TAB_RECENT -> TAB_TITLE_RECENT
else -> TAB_TITLE_RECOMMENDED
}
}.attach()
}
viewModel.recommendedList.observe(viewLifecycleOwner, Observer {
sendDataToFragment(POSITION_TAB_RECOMMENDED, it)
})
viewModel.recentList.observe(viewLifecycleOwner, Observer {
sendDataToFragment(POSITION_TAB_RECENT, it)
})
}
override fun onAttach(context: Context) {
super.onAttach(context)
retainInstance = true
}
private fun sendDataToFragment(fragmentPosition: Int, productList: PagedList<Product>?) {
val mFragment: Fragment? =
(viewPager.adapter as? ProductTabPagerAdapter)?.tabFragments?.get(fragmentPosition)
mFragment?.let { (it as? ProductFragment)?.setUpListData(productList) }
}
companion object {
const val POSITION_TAB_RECOMMENDED = 0
const val POSITION_TAB_RECENT = 1
private const val TAB_TITLE_RECOMMENDED = "RECOMMENDED"
private const val TAB_TITLE_RECENT = "RECENT"
#JvmStatic
fun newInstance() = ProductTabFragment()
}
}
Pager Adapter
class ProductTabPagerAdapter(fragmentManager: FragmentManager,
lifecycle: Lifecycle, val tabCount :Int) :
FragmentStateAdapter(fragmentManager,lifecycle) {
internal var tabFragments = listOf<Fragment>(ProductFragment.newInstance(ProductTabFragment.POSITION_TAB_RECOMMENDED),ProductFragment.newInstance(ProductTabFragment.POSITION_TAB_RECENT))
override fun getItemCount(): Int {
return tabCount
}
override fun createFragment(position: Int): Fragment {
return tabFragments[position]
}
}
**Same Reusable fragments used in ViewPager**
class ProductFragment : Fragment() {
private var productAdapter = ProductPagedListAdapter()
#Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
private val viewModel: ProductViewModel by viewModels(
ownerProducer = { activity as FragmentActivity },
factoryProducer = { viewModelFactory }
)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? = inflater.inflate(R.layout.productÆ’_fragment, container, false)?.apply {
initialProgressBar = findViewById(R.id.initialLoadProgressBar)
loadMoreProgressBar = findViewById(R.id.loadMoreProgressBar)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.findViewById<RecyclerView>(R.id.productList)?.apply {
context?.also { ctx ->
layoutManager = LinearLayoutManager(ctx)
}
adapter = productAdapter
}
}
fun setUpListData(data: PagedList<Product>?) {
productAdapter.submitList(data)
}
override fun onAttach(context: Context) {
super.onAttach(context)
retainInstance = true
}
}
Paged List Adapater
class ProductPagedListAdapter() : PagedListAdapter<Product, ProductItemHolder>(diffUtilCallBack) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductItemHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.product_item, parent, false)
return ProductItemHolder(view)
}
override fun onBindViewHolder(holder: ProductItemHolder, position: Int) {
getItem(position)?.let { holder.bind(it) }
}
companion object {
var diffUtilCallBack = object : DiffUtil.ItemCallback<Product>() {
override fun areItemsTheSame(
oldItem: Product,
newItem: Product
) = oldItem.id == newItem.id
override fun areContentsTheSame(
oldItem: Product,
newItem: Product
)= oldItem == newItem
}
}
}
View Model
class ProductViewModel()) : ViewModel() {
var recommendedList : LiveData<PagedList<Product>> = MutableLiveData<PagedList<Product>>()
var recentList : LiveData<PagedList<Product>> = MutableLiveData<PagedList<Product>>()
init {
fetchRecentProducts()
fetchRecommended()
}
fun fetchRecommended() {
val pagedListConfig = PagedList.Config.Builder()
.setPageSize(ProductDataSource.PAGE_LIMIT)
.setEnablePlaceholders(false).build()
val dataSourceFactory = object : DataSource.Factory<Int, Product>() {
override fun create(): DataSource<Int, Product> {
return ProductDataSource(
type = "recommended",
)
}
}
recommendedList = LivePagedListBuilder<Int, Product>(
dataSourceFactory,
pagedListConfig
).build()
}
fun fetchRecent() {
val pagedListConfig = PagedList.Config.Builder()
.setPageSize(ProductDataSource.PAGE_LIMIT)
.setEnablePlaceholders(false).build()
val dataSourceFactory = object : DataSource.Factory<Int, Product>() {
override fun create(): DataSource<Int, Product> {
return ProductDataSource(
type = "recent",
)
}
}
recentList = LivePagedListBuilder<Int, Product>(
dataSourceFactory,
pagedListConfig
).build()
}
fun resetPaginationData() {
recommendedList.value?.dataSource?.invalidate()
recentList.value?.dataSource?.invalidate()
}
}
Data Source for paged List
class ProductDataSource(
private val type: String) : PageKeyedDataSource<Int, Product>() {
override fun loadInitial(
params: LoadInitialParams<Int>,
callback: LoadInitialCallback<Int, Product>
) {
compositeDisposable.add(
productRepo.getProductList(
tyoe
).subscribe(
{ productList ->
callback.onResult(
productList, null, PAGE_LIMIT
)
}
)
}
}

Sharing recyclerview item ID with another fragment

Currently I have a recyclerview adapter that gets data from the database and displays it in the dashboard fragment. Once the item is clicked, I want to pass the item id to the details fragment to get the correct items information on the detailed view. How can I pass this ID to the detailed fragment?
Dashboard Fragment
class DashboardFragment : Fragment() {
private lateinit var viewModel: DashboardViewModel
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Get a reference to the binding object and inflate the fragment views.
val binding: DashboardFragmentBinding = DataBindingUtil.inflate(
inflater, R.layout.dashboard_fragment, container, false)
val application = requireNotNull(this.activity).application
val dataSource = NumberDatabase.getInstance(application).numberDatabaseDao
val viewModelFactory = DashboardViewModelFactory(dataSource, application)
// Get a reference to the ViewModel associated with this fragment.
val dashboardViewModel =
ViewModelProviders.of(
this, viewModelFactory).get(DashboardViewModel::class.java)
// To use the View Model with data binding, you have to explicitly
// give the binding object a reference to it.
binding.dashboardViewModel = dashboardViewModel
val adapter = CounterAdapter(CounterListener { nightId ->
dashboardViewModel.onCountClicked(nightId)
})
binding.counterList.adapter = adapter
dashboardViewModel.counts.observe(viewLifecycleOwner, Observer {
it?.let {
adapter.submitList(it)
}
})
}
Adapter
class CounterAdapter (val clickListener: CounterListener): ListAdapter<Number, CounterAdapter.ViewHolder>(NightDiffCallback()) {
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(getItem(position)!!, clickListener)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder.from(parent)
}
class ViewHolder private constructor(val binding: ListItemCounterBinding) : RecyclerView.ViewHolder(binding.root){
fun bind(item: Number, clickListener: CounterListener) {
binding.night = item
binding.clickListener = clickListener
binding.executePendingBindings()
}
companion object {
fun from(parent: ViewGroup): ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding = ListItemCounterBinding.inflate(layoutInflater, parent, false)
return ViewHolder(binding)
}
}
}
}
class CounterListener(val clickListener: (nightId: Long) -> Unit) {
fun onClick(night: Number) = clickListener(night.nightId)
}
In your recyclerview
class RecipeRecyclerAdapter(
mFragmentCommunication: FragmentCommunication
) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var mFragmentCommunication: FragmentCommunication? = null
init {
this.mFragmentCommunication =mFragmentCommunication
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
RecyclerView.ViewHolder {
view = LayoutInflater.from(parent.context)
.inflate(
com.broadcast.recipeslistapp.R.layout.layout_recipe_list_item,
parent,
false
)
return RecipeViewHolder(view)
}
}
override fun getItemCount(): Int {
if (mRecipes.isNullOrEmpty()) {
return 0
} else {
return mRecipes!!.size
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
holder.itemView.setOnClickListener {
mFragmentCommunication!!.PassNightId(nightId = 1) //value of nightId
}
}
interface FragmentCommunication {
fun PassNightId(nightId: Int)
}
Fragment A from where you want to send data :
class RecipeListActivity : BaseActivity(),
RecipeRecyclerAdapter.FragmentCommunication {
private lateinit var layoutManager: LinearLayoutManager
}
private fun initRecyclerView() {
mAdapter = RecipeRecyclerAdapter( this)
val itemDecorator = VerticalSpacingItemDecorator(30);
recipe_list.addItemDecoration(itemDecorator);
recipe_list.adapter = mAdapter
layoutManager = LinearLayoutManager(this);
recipe_list.layoutManager = layoutManager
}
override fun PassNightId(nightId: Int) {
val testFragment = TestFragment()
val bundle = Bundle()
bundle.putString("nightId", "$nightId")
testFragment.arguments = bundle
supportFragmentManager.beginTransaction().replace(R.id.containerId,testFragment).commit()
}
}
Fragment B where you want to getData :
class TestFragment : Fragment()
{
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val nightId =arguments?.getString("nightId")
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.test_fragment,container,false)
}
}
This is how you can send data from on fragment to another fragment.

Categories

Resources