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()