java.lang.IllegalStateException: Fragment already added: InprogressFragment - android

When I click on order menu the app suddenly stopped working, and on the log show this error
image, it says java.lang.IllegalStateException: Fragment already added: InprogressFragment
I have 2 section pager on order menu, it's for inprogress & pastOrders.
here is the code
inProgressFragment:
class InprogressFragment : Fragment(), InprogressAdapter.ItemAdapterCallback {
private var adapter: InprogressAdapter? = null
private var inprogressList: ArrayList<Data>? = ArrayList()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_inprogress, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
inprogressList = arguments?.getParcelableArrayList("data")
if (!inprogressList.isNullOrEmpty()) {
adapter = InprogressAdapter(inprogressList!!, this)
val layoutManager: RecyclerView.LayoutManager = LinearLayoutManager(activity)
rvList.layoutManager = layoutManager
rvList.adapter = adapter
}
}
override fun onClick(v: View?, data: Data) {
val detail = Intent(activity, OrdersDetailActivity::class.java).putExtra("data", data)
startActivity(detail)
}
}
OrderFragment:
class OrderFragment : Fragment(), OrderContract.View{
lateinit var presenter: OrderPresenter
var progressDialog: Dialog? = null
private var inprogressList: ArrayList<Data>? = ArrayList()
private var pastordersList: ArrayList<Data>? = ArrayList()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_order, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
initView()
presenter = OrderPresenter(this)
presenter.getTransaction()
}
override fun onTransactionSuccess(transactionResponse: TransactionResponse) {
Log.v("tamvan", "ini token "+IcaCraft.getApp().getToken())
if (transactionResponse.data.isNullOrEmpty()) {
include_toolbar.visibility = View.GONE
ll_tab.visibility = View.GONE
ll_empty.visibility = View.VISIBLE
} else {
for (a in transactionResponse.data.indices) {
// past order
if (transactionResponse.data[a].status.equals("ON_DELIVERY", true)
|| transactionResponse.data[a].status.equals("PENDING", true)) {
inprogressList?.add(transactionResponse.data[a])
// progress
} else if (transactionResponse.data[a].status.equals("DELIVERY", true)
|| transactionResponse.data[a].status.equals("DELIVERED", true)
|| transactionResponse.data[a].status.equals("CANCELLED", true)
|| transactionResponse.data[a].status.equals("SUCCESS", true)) {
pastordersList?.add(transactionResponse.data[a])
}
}
if (inprogressList.isNullOrEmpty() && pastordersList.isNullOrEmpty()) {
include_toolbar.visibility = View.GONE
ll_tab.visibility = View.GONE
ll_empty.visibility = View.VISIBLE
} else {
val sectionsPagerAdapter = SectionsPagerAdapter(
childFragmentManager
)
sectionsPagerAdapter.setData(inprogressList, pastordersList)
//viewPager!!.offscreenPageLimit = 3
viewPager.adapter = sectionsPagerAdapter
tabLayout.setupWithViewPager(viewPager)
}
}
}
override fun onTransactionFailed(message: String) {
Toast.makeText(activity, message, Toast.LENGTH_LONG).show()
}
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)
}
include_toolbar.toolbar.title = "Your Orders"
include_toolbar.toolbar.subtitle = "Wait for the best meal"
}
override fun showLoading() {
progressDialog?.show()
}
override fun dismissLoading() {
progressDialog?.dismiss()
}
}
SectionPagerAdapter:
class SectionsPagerAdapter(fm: FragmentManager) :
FragmentPagerAdapter(
fm
) {
var inprogressList: ArrayList<Data>? = ArrayList()
var pastOrdersList: ArrayList<Data>? = ArrayList()
override fun getItem(position: Int): Fragment {
var fragment : Fragment
return when (position) {
0 -> {
fragment = InprogressFragment()
val bundle = Bundle()
bundle.putParcelableArrayList("data", inprogressList)
fragment.setArguments(bundle)
return fragment
}
1 -> {
fragment = PastordersFragment()
val bundle = Bundle()
bundle.putParcelableArrayList("data", pastOrdersList)
fragment.setArguments(bundle)
return fragment
}
else -> {
fragment = InprogressFragment()
val bundle = Bundle()
bundle.putParcelableArrayList("data", inprogressList)
fragment.setArguments(bundle)
return fragment
}
}
}
override fun getPageTitle(position: Int): CharSequence? {
return when (position) {
0 -> "In Progress"
1 -> "Past Orders"
else -> null
}
}
override fun getCount(): Int {
return 2
}
fun setData(inprogressListParms: ArrayList<Data>?, pastOrdersListParms: ArrayList<Data>?) {
inprogressList = inprogressListParms
pastOrdersList = pastOrdersListParms
}
}

Try something like this(I didn't test this code, it's just a concept for your app):
enum class FragmentType {
IN_PROGRESS,
POSTORDERS
}
data class Data(
val fragmentType: FragmentType,
val fragmentName: String,
val orderList: ArrayList<Data>?
)
class SectionsPagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) {
var inprogressList: ArrayList<Data> = ArrayList()
override fun getItem(position: Int): Fragment {
val item = inprogressList[position]
return when (item.fragmentType) {
FragmentType.IN_PROGRESS -> {
InprogressFragment().apply {
val bundle = Bundle()
bundle.putParcelableArrayList("data", item.orderList)
setArguments(bundle)
}
}
FragmentType.POSTORDERS -> {
PastordersFragment().apply {
val bundle = Bundle()
bundle.putParcelableArrayList("data", item.orderList)
setArguments(bundle)
}
}
}
}
override fun getPageTitle(position: Int): CharSequence {
return inprogressList[position].fragmentName
}
override fun getCount(): Int {
return inprogressList.size
}
fun setData(items: ArrayList<Data>) {
inprogressList = items
notifyDataSetChanged()
}
}

Related

Fragment screen switching when clicking recycler view item

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

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.

java.lang.IllegalArgumentException: Required argument "data" is missing and does not have an android:defaultValue

I try to pass data from API on recycleView on Home Activity to new activity and fragment, but I have a problem like this
java.lang.IllegalArgumentException: Required argument "data" is missing and does not have an android:defaultValue
at com.project.icacraft.ui.detail.DetailFragmentArgs$Companion.fromBundle(DetailFragmentArgs.kt:60)
at com.project.icacraft.ui.detail.DetailFragment.onActivityCreated(DetailFragment.kt:35)
I have 2 recycleView, horizontal and vertical, here is my code for HomeAdapter:
class HomeAdapter (
private val listData: List<Data>,
private val itemAdapterCallback: ItemAdapterCallback
) : RecyclerView.Adapter<HomeAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val view = layoutInflater.inflate(R.layout.item_home_horizontal, 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
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)
}
}
HomePresenter:
class HomePresenter (private val view:HomeContract.View) : HomeContract.Presenter{
private val mCompositeDisposable : CompositeDisposable?
init {
this.mCompositeDisposable = CompositeDisposable()
}
override fun getHome() {
view.showLoading()
val disposable = HttpClient.getInstance().getAPI()!!.home()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
view.dismissLoading()
if (it.meta?.status.equals("success")){
it.data?.let { data -> view.onHomeSuccess(data) }
} else {
view.onHomeFailed(it.meta?.message.toString())
}
},
{
view.dismissLoading()
view.onHomeFailed(it.getErrorBodyMessage())
}
)
mCompositeDisposable!!.add(disposable)
}
override fun subscribe() {}
override fun unSubscribe() {
mCompositeDisposable!!.clear()
}
}
Here is the code for Horizontal Recycleview on home:
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)
}
//menampilakn foto user
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!!.offscreenPageLimit = 3
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()
}
}
Code for SectionPagerAdapter
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
}
}
Here is code for vertical recycleview adapter:
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)
}
}
Code for vertical recycleview fragment:
class HomeNewCraftFragment : Fragment(), HomeNewCraftAdapter.ItemAdapterCallback {
private var adapter: HomeNewCraftAdapter? = null
private var newcraftlist: java.util.ArrayList<Data>? = java.util.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)
}
}
And I want to pass data here, on Detail Activity:
class DetailActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_detail)
intent.extras?.let {
val navController = Navigation.findNavController(findViewById(R.id.detailHostFragment))
val bundle = Bundle()
bundle.putParcelable("data", it.get("data") as Parcelable?)
navController.setGraph(navController.graph, bundle)
}
}
fun toolbarPayment() {
toolbar.visibility = View.VISIBLE
toolbar.title = "Payment"
toolbar.subtitle = "You deserve better meal"
toolbar.navigationIcon = resources.getDrawable(R.drawable.arrow_back)
toolbar.setNavigationOnClickListener { onBackPressed() }
}
fun toolbarDetail() {
toolbar.visibility = View.GONE
}
}
And fragment:
class DetailFragment : Fragment() {
var data:Data?= null
var bundle:Bundle?= null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_detail, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
(activity as DetailActivity?)!!.toolbarDetail()
arguments?.let {
DetailFragmentArgs.fromBundle(it).data.let {
initView(it)
}
}
btnOrderNow.setOnClickListener { view ->
Navigation.findNavController(view).navigate(R.id.action_fragmentDetail_to_fragmentPayment, bundle)
}
}
private fun initView(data: Data?) {
bundle = bundleOf("data" to data)
Glide.with(requireContext())
.load(data?.picturePath)
.into(ivPoster)
tvTitle.text = data?.name
tvDescription.text = data?.description
tvMaterials.text = data?.materials
// tvTotal.formatPrice(data?.price.toString())
}
}
and here is the navigation:
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
app:startDestination="#id/fragmentDetail"
android:id="#+id/nav_detail">
<fragment
android:id="#+id/fragmentDetail"
android:name="com.project.icacraft.ui.detail.DetailFragment"
tools:layout="#layout/fragment_detail">
<action
android:id="#+id/action_fragmentDetail_to_fragmentPayment"
app:destination="#id/fragmentPayment" />
<argument
android:name="data"
app:argType="com.project.icacraft.model.response.home.Data"
app:nullable="true" />
</fragment>
Here is xml for activiy_detail:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.detail.DetailActivity">
//Menambahkan toolbar dan detail fragment
<include
android:id="#+id/include_toolbar"
layout="#layout/layout_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<fragment
android:id="#+id/detailHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_detail"
/>
</LinearLayout>
As per the Pass data to the start destination documentation:
Note: when manually calling setGraph() with arguments, you must not use the app:navGraph attribute when creating the NavHostFragment in XML as that will internally call setGraph() without any arguments, resulting in your graph and start destination being created twice.
So you can fix your error by removing the app:navGraph="#navigation/nav_detail" line from your activity_detail.xml file.
You'll also need to change your setGraph call to use the same R.navigation.nav_detail:
navController.setGraph(R.navigation.nav_detail, bundle)

Dynamic ViewPager open new activity from Viewpager and I lost my views when go back

I have a dynamic Viewpager and I add pages with title. In Viewpager I have and Setting button that sends you in new Activity but when I go back in ViewPager all my views which I have added have deleted. What should I do to not lose views??
class MainActivity : AppCompatActivity() {
private var btn_add: ImageButton? = null
private var btn_setting: ImageButton? = null
private var txtQRCode : TextView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val globalClass = applicationContext as GlobalClass
btn_add = findViewById(R.id.btn_add)
btn_setting = findViewById(R.id.btn_Setting)
globalClass.getFragmentList()
globalClass.getFragmentTitleList()
globalClass.getFragmentBtnCloseList()
btn_add!!.setOnClickListener { showDialogAdd() }
btn_setting!!.setOnClickListener {
val intent = Intent(this#MainActivity, Setting::class.java)
//Log.d("Getmartios", globalClass.getFragmentTitleList().toString())
startActivity(intent)
}
txtQRCode = findViewById(R.id.txtQRCode)
txtQRCode!!.setText(globalClass.getBarcodeData())
}
private fun showDialogAdd() {
val dialog = Dialog(this, R.style.DialogStyle)
dialog.setContentView(R.layout.layout_custom_dialog_addthermostat)
//dialog.window!!.setBackgroundDrawableResource(R.drawable.bg_window)
val btnClose = dialog.findViewById<ImageView>(R.id.btn_close_add_thermostat)
var fragmentParent: FragmentParent? = null
fragmentParent = this.supportFragmentManager.findFragmentById(R.id.fragmentParent) as FragmentParent?
val editText_Serial_Number = dialog.findViewById<TextView>(R.id.editText_Serial_Number)
val btnOK = dialog.findViewById<Button>(R.id.btn_ok)
btnOK.setOnClickListener {
if(editText_Serial_Number.text.toString()!= ""){
fragmentParent!!.addPage(editText_Serial_Number!!.text.toString() + "")
editText_Serial_Number.text = ""
}
dialog.dismiss()
}
btnClose.setOnClickListener { dialog.dismiss() }
dialog.show()
}
}
FragmentParent
class FragmentParent : Fragment() {
private var tabLayout: TabLayout? = null
private var viewPager: ViewPager? = null
private var adapter: ViewPagerAdapter? = null
//var btn_Settings: ImageButton? = null
#Nullable
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val view: View = inflater.inflate(R.layout.fragment_parent, container, false)
getIDs(view)
setEvents()
return view
}
private fun getIDs(view: View) {
viewPager = view.findViewById<View>(R.id.my_viewpager) as ViewPager
tabLayout = view.findViewById<View>(R.id.my_tab_layout) as TabLayout
viewPager!!.offscreenPageLimit = 20
adapter = getActivity()?.let { ViewPagerAdapter(getFragmentManager(), it, viewPager!!, tabLayout!!) }
viewPager!!.setAdapter(adapter)
}
var selectedTabPosition = 0
private fun setEvents() {
tabLayout!!.setOnTabSelectedListener(object : TabLayout.ViewPagerOnTabSelectedListener(viewPager) {
override fun onTabSelected(tab: TabLayout.Tab) {
super.onTabSelected(tab)
viewPager!!.setCurrentItem(tab.getPosition())
selectedTabPosition = viewPager!!.getCurrentItem()
Log.d("Selected", "Selected " + tab.getPosition())
}
override fun onTabUnselected(tab: TabLayout.Tab) {
super.onTabUnselected(tab)
Log.d("Unselected", "Unselected " + tab.getPosition())
}
})
}
fun addPage(pagename: String?) {
val bundle = Bundle()
bundle.putString("data", pagename)
val fragmentChild = FragmentChild()
fragmentChild.setArguments(bundle)
adapter!!.addFrag(fragmentChild, pagename!!, false)
adapter!!.notifyDataSetChanged()
if (adapter!!.getCount() > 0) tabLayout!!.setupWithViewPager(viewPager)
viewPager!!.setCurrentItem(adapter!!.getCount() - 1)
setupTabLayout()
}
fun setupTabLayout() {
selectedTabPosition = viewPager!!.getCurrentItem()
for (i in 0 until tabLayout!!.getTabCount()) {
tabLayout!!.getTabAt(i)!!.customView
}
}
}
This is the fragment which inherite the views that creates from the Add Button
class FragmentChild : Fragment() {
var childname: String? = null
var textViewChildName: TextView? = null
var editText: TextView? = null
#Nullable
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val view: View = inflater.inflate(R.layout.fragment_child, container, false)
val bundle: Bundle? = getArguments()
childname = bundle!!.getString("data")
getIDs(view)
setEvents()
return view
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
}
private fun getIDs(view: View) {
textViewChildName = view.findViewById<View>(R.id.textViewChild) as TextView
textViewChildName!!.text = childname
editText = view.findViewById<View>(R.id.editText) as TextView
editText!!.setText("")
}
private fun setEvents() {}
}
In this class I create the list with fragments
class ViewPagerAdapter(manager: FragmentManager?, var context: Context, viewPager: ViewPager, tabLayout: TabLayout) : FragmentStatePagerAdapter(manager!!) {
private val mFragmentList: ArrayList<Fragment> = ArrayList<Fragment>()
private val mFragmentTitleList = ArrayList<String>()
private val mFragmentBtnCloseList = ArrayList<Boolean>()
override fun getItem(position: Int): Fragment {
return mFragmentList[position]
}
override fun getCount(): Int {
return mFragmentList.size
}
fun addFrag(fragment: Fragment, title: String, btn_close: Boolean) {
mFragmentList.add(fragment)
mFragmentTitleList.add(title)
mFragmentBtnCloseList.add(btn_close)
val globalClass = context.getApplicationContext() as GlobalClass
globalClass.setFragmentList(mFragmentList)
globalClass.setFragmentTitleList(mFragmentTitleList)
globalClass.setFragmentBtnCloseList(mFragmentBtnCloseList)
Log.d("setFragmentList", mFragmentList.toString())
Log.d("mFragmentTitleList", mFragmentTitleList.toString())
}
}
Here is the Setting Page with back button with globalClass i see I have
the data but when go back in Main Activity I lose my data
Setting
class Setting : AppCompatActivity() {
private var btn_back: Button? = null
var fragmentParent: FragmentParent? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_setting)
val globalClass = applicationContext as GlobalClass
fragmentParent = this.supportFragmentManager.findFragmentById(R.id.fragmentParent) as FragmentParent?
btn_back = findViewById(R.id.btn_back)
btn_back!!.setOnClickListener {
val intent = Intent(this#Setting, MainActivity::class.java)
//fragmentParent!!.marios()
globalClass.getFragmentList()
globalClass.getFragmentTitleList()
globalClass.getFragmentBtnCloseList()
startActivity(intent)
}
}
}

RecyclerView never show

I try get data from internet, after done i update my Recyclerview, but it never show. Method onDone() Toast size of result, it's not empty.
My code:
class SearchFragment : Fragment() {
private lateinit var requestSearchPresenter: RequestSearchPresenter
private lateinit var recyclerViewAdapter: RecyclerViewAdapter
private var searchResult = ArrayList<ItemNewFeedCollection?>()
private val onRequestSearchResult = object : OnRequestSearchResult {
override fun onEmpty(result: ListNewFeedCollection) {
recyclerViewAdapter.notifyDataSetChanged()
}
override fun onDone(result: ListNewFeedCollection) {
searchResult = result.post
Toast.makeText(requireContext(), "${searchResult.size}", Toast.LENGTH_SHORT).show()
recyclerViewAdapter.notifyDataSetChanged()
}
override fun onFail(t: String) {
recyclerViewAdapter.notifyDataSetChanged()
}
}
private var recyclerViewItemClickListener = object : OnRecyclerViewItemClickListener {
override fun onItemClick(view: View, postion: Int) {
(requireActivity() as NewFeedActivity).apply {
val post = searchResult
if (post[postion]!!.date == "null" && post[postion]!!.date == post[postion]!!.description &&
post[postion]!!.date == post[postion]!!.full_post && post[postion]!!.date == post[postion]!!.image &&
post[postion]!!.date == post[postion]!!.full_post
) {
} else {
val link = post[postion]!!.link
val source = post[postion]!!.source
val intent = Intent(requireContext(), PostActivity::class.java)
intent.putExtra("link", link)
intent.putExtra("source", source)
startActivity(intent)
}
}
}
override fun onLongItemClick(view: View, postion: Int) {
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_search, container, false)
}
private fun configRecyclerView() {
recyclerViewAdapter = RecyclerViewAdapter(requireContext(), searchResult, recyclerViewItemClickListener)
recycler_view.layoutManager = LinearLayoutManager(requireContext())
recycler_view.adapter = recyclerViewAdapter
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
configRecyclerView()
val keyWord = arguments?.getString("key_word")
keyWord?.let {
requestSearchPresenter = RequestSearchPresenter(onRequestSearchResult)
requestSearchPresenter.search(it)
}
}
}
But i move method configRecyclerView() to onDone(), it show on:
override fun onDone(result: NewFeedCollection) {
searchResult = result.post
Toast.makeText(requireContext(), "${searchResult.size}", Toast.LENGTH_SHORT).show()
configRecyclerView()
recyclerViewAdapter.notifyDataSetChanged()
}
in fun onDone you are reassigning the result: searchResult = result.post
Instead of that you have to update the list's reference you've passed to the adapter initially. That means you need to change the code:
from:
searchResult = result.post
to
searchResult.clear();
searchResult.addAll(result.post);

Categories

Resources