Home > Software engineering >  RecyclerView doesn't appear in a Fragment
RecyclerView doesn't appear in a Fragment

Time:03-10

Why doesn't RecyclerView appear in my fragment? I've added recyclerview adapter in the fragment, but it still didn't appear. Here are the codes:

FollowersFragment.kt

class FollowersFragment : Fragment() {
    private lateinit var binding: FragmentFollowersBinding
 
    companion object {
        private const val TAG = "FollowersFragment"
        const val ARG_NAME = "userName"
    }
 
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_followers, container, false)
    }
 
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding = FragmentFollowersBinding.inflate(layoutInflater)
 
        val username = arguments?.getString(ARG_NAME)
 
        val layoutManager = LinearLayoutManager(requireActivity())
        binding.rvFollowers.layoutManager = layoutManager
        val itemDecoration = DividerItemDecoration(requireActivity(), layoutManager.orientation)
        binding.rvFollowers.addItemDecoration(itemDecoration)
 
        val client = ApiConfig.getApiService().getFollowers(username.toString(),"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")
        client.enqueue(object : Callback<List<FollowsResponseItem>> {
            override fun onResponse(
                call: Call<List<FollowsResponseItem>>,
                response: Response<List<FollowsResponseItem>>
            ) {
                if(response.isSuccessful){
                    val responseBody = response.body()
                    if(responseBody!=null){
                        Log.d(TAG,responseBody.toString())
                        setUserData(responseBody)
                    }else{
                        Log.e(TAG,"onFailure: ${response.message()}")
                    }
                }
            }
 
            override fun onFailure(call: Call<List<FollowsResponseItem>>, t: Throwable) {
                Log.e(TAG, "onFailure: ${t.message}")
            }
        })
    }
 
    fun setUserData(item: List<FollowsResponseItem>){
        val listUser = ArrayList<UserResponse>()
        val executor = Executors.newSingleThreadExecutor()
        executor.execute {
            try {
                for (i in 0..item.size-1) {
                    if(item.size>5 && i>5){
                        break
                    }
                    val client = ApiConfig.getApiService()
                        .getUser(item.get(i).login, "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")
                    client.enqueue(object : Callback<UserResponse> {
                        override fun onResponse(
                            call: Call<UserResponse>,
                            response: Response<UserResponse>
                        ) {
                            if (response.isSuccessful) {
                                val responseBody = response.body()
                                if (responseBody != null) {
                                    listUser.add(responseBody)
                                    if(i==4 || item.get(i).login.equals(item.get(item.size-1).login)){
                                        Log.d(TAG,"user : $listUser")
                                        val adapter = ListUserAdapter(listUser)
                                        binding.rvFollowers.adapter = adapter
                                        Log.d(TAG,adapter.toString())
                                        adapter.setOnItemClickCallback(object: ListUserAdapter.OnItemClickCallback{
                                            override fun onItemClicked(data: UserParcelable) {
                                                showSelectedUser(data)
                                            }
                                        })
                                    }
                                } else {
                                    Log.e(TAG, "onFailure: ${response.message()}")
                                }
                            }
                        }
 
                        override fun onFailure(call: Call<UserResponse>, t: Throwable) {
                            Log.e(TAG, "onFailure: ${t.message}")
                        }
                    })
                }
            } catch(e: InterruptedException) {
                e.printStackTrace()
            }
        }
    }
 
    private fun showSelectedUser(data: UserParcelable) {
 
    }
}

DetailActivity.kt

class DetailActivity : AppCompatActivity() {
    private  lateinit var binding: ActivityDetailBinding
    private var getUserName: String ="sidiqpermana"
    companion object{
        const val EXTRA_DATA = "extra_data"
        @StringRes
        private  val TAB_TITLES = intArrayOf(
            R.string.tab_text_1,
            R.string.tab_text_2
        )
 
    }
    @SuppressLint("SetTextI18n")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
 
        supportActionBar?.hide()
        binding = ActivityDetailBinding.inflate(layoutInflater)
        setContentView(binding.root)
 
        val data = intent.getParcelableExtra<UserParcelable>(EXTRA_DATA) as UserParcelable
        val sectionsPagerAdapter = SectionsPagerAdapter(this)
        val viewPager: ViewPager2 = binding.viewPager
        viewPager.adapter = sectionsPagerAdapter
        val tabs: TabLayout = binding.tabs
        sectionsPagerAdapter.userName = data.login
 
        TabLayoutMediator(tabs,viewPager){ tab, position ->
            tab.text = resources.getString(TAB_TITLES[position])
        }.attach()
 
        getUserName = data.login
 
        showInfo(data)
 
 
    }
 
    fun getUserName() : String{
        return getUserName
    }
    @SuppressLint("SetTextI18n")
    private fun showInfo(data: UserParcelable){
        Glide.with(this@DetailActivity)
            .load(data.avatar_url)
            .into(binding.detailPp)
        if(data.name.equals("null")) binding.detailName.setText("No Name") else binding.detailName.setText(data.name)
        binding.detailUsername.setText(data.login)
        if(data.bio.equals("null")) binding.detailBio.setText("No Name") else binding.detailBio.setText(data.bio)
        binding.detailFollowers.setText("${data.followers} Followers")
        binding.detailFollowings.setText("${data.following} Following")
        if(data.location.equals("null")) binding.detailLocation.setText("No Location") else binding.detailLocation.setText(data.location)
    }
}

ListUserAdapter.kt (RecyclerView Adapter)

class ListUserAdapter (private val listUser: ArrayList<UserResponse>) : RecyclerView.Adapter<ListUserAdapter.ListViewHolder>() {
    private lateinit var onItemClickCallback: OnItemClickCallback
 
    fun setOnItemClickCallback(onItemClickCallback: OnItemClickCallback){
        this.onItemClickCallback = onItemClickCallback
    }
 
class ListViewHolder(var binding: ItemUsersRowBinding) : RecyclerView.ViewHolder(binding.root) {
 
    }
 
    override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ListViewHolder {
        val binding = ItemUsersRowBinding.inflate(LayoutInflater.from(viewGroup.context),viewGroup,false)
        return ListViewHolder(binding)
    }
 
    @SuppressLint("SetTextI18n")
    override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
        var (followers,avatar_url,following, name,bio, location, login) = listUser[position]
        name = name ?: "No Name"
        bio = bio ?: "No Bio"
        location = location?: "No Location"
        holder.apply {
            Glide.with(itemView.getContext())
                .load(avatar_url)
                .into(binding.photoProfile)
            binding.profileName.setText(name.toString())
            binding.username.setText(login)
            binding.followers.setText("$following Followers")
            binding.followings.setText("$following Followings")
            binding.location.setText(location.toString())
 
            val detailUser = UserParcelable(followers,avatar_url,following,
                name.toString(), bio.toString(), location.toString(), login)
            itemView.setOnClickListener{ onItemClickCallback.onItemClicked(detailUser)}
        }
 
    }
 
    override fun getItemCount(): Int {
        return listUser.size
    }
 
    interface OnItemClickCallback {
        fun onItemClicked(data: UserParcelable)
    }
}

Help me solve this problem please.

CodePudding user response:

There is no need to initialize adapter every time you want to update the list. Either make your ListUserAdapter extend ListAdapter and than use adapter.submitList(listUser) or if you want to extend RecyclerView.Adapter as you do, you can do the following :

class ListUserAdapter () : RecyclerView.Adapter<ListUserAdapter.ListViewHolder>() {

  private val listUser: List<UserResponse>

  fun submitList(newList: List<UserResponse>) {
     listUser = newList
     notifyDataSetChanged()
  }

  override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
    val listItem = listUser[position]
    ...
  }


  override fun getItemCount(): Int {
    return listUser.size
  }
}

I suggest you go with ListAdapter. Check if Log.d(TAG,"user : $listUser") is printed, if it is and listUser is not empty than call adapter.submitList(listUser) and RV should be populated.

CodePudding user response:

You have missed to notify adapter about the changes, So after binding.rvFollowers.adapter = adapter call adapter.notifyDataSetChanged()

  • Related