I want to use recyclerView, but the view doesn't have any values. kotlin - kotlin

class SummonerInfoActivity: AppCompatActivity() {
private lateinit var participantAdapter: ParticipantAdapter
private val recycler: RecyclerView by lazy {
findViewById(R.id.RecyclerView)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val Summoner = intent.getParcelableExtra<SummonerDTO>("SummonerDTO")
Log.e("Info","${Summoner}")
val retrofit2 = Retrofit.Builder()
.baseUrl("https://asia.api.riotgames.com")
.addConverterFactory(GsonConverterFactory.create())
.build()
lolAPIForMatch = retrofit2.create(lolAPIService::class.java)
setContentView(R.layout.activity_summoner_info)
participantAdapter = ParticipantAdapter()
recycler.adapter = participantAdapter
recycler.layoutManager = LinearLayoutManager(this#SummonerInfoActivity)
getMatchIdBypuuid(Summoner?.puuId.orEmpty(),Summoner?.summonerName.orEmpty())
}
private fun getMatchIdBypuuid(puuid: String,summonerName: String){
lolAPIForMatch.getMatchIdBypuuid(puuid, 0,20, API_KEY)
.enqueue(object : Callback<List<String>> {
override fun onResponse(
call: Call<List<String>>,
response: Response<List<String>>
) {
if(response.isSuccessful.not()){
return
}
response.body()?.let {
it.forEach {
searchMatchInfoByMatchID(it,summonerName)
}
}
}
override fun onFailure(call: Call<List<String>>, t: Throwable) {
}
})
}
private fun searchMatchInfoByMatchID(matchId: String,summonerName: String){
lolAPIForMatch.getMatchInfoByMatchID(matchId, API_KEY)
.enqueue(object : Callback<MatchDTO>{
override fun onResponse(call: Call<MatchDTO>, response: Response<MatchDTO>) {
if(response.isSuccessful.not()){
return
}
response.body()?.let {
it.info.participants.filter {
it.summonerName == "${summonerName}"
}.forEach {
participantAdapter.participants.add(it)
}
}
}
override fun onFailure(call: Call<MatchDTO>, t: Throwable) {
}
})
}
}
class ParticipantAdapter: RecyclerView.Adapter<ParticipantAdapter.ViewHolder>() {
var participants = mutableListOf<ParticipantDTO>()
inner class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
fun bind(participant: ParticipantDTO){
itemView.findViewById<TextView>(R.id.kill).text = participant.kills.toString()
itemView.findViewById<TextView>(R.id.death).text = participant.deaths.toString()
itemView.findViewById<TextView>(R.id.assist).text = participant.assists.toString()
}
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ParticipantAdapter.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return ViewHolder(inflater.inflate(R.layout.item_match, parent, false))
}
override fun onBindViewHolder(holder: ParticipantAdapter.ViewHolder, position: Int) {
holder.bind(participants[position])
}
override fun getItemCount(): Int {
return participants.size
}
}
participantAdapter.participants.add(it)
The command is searchMatchInfoByMatchID
In the function, you can check that the value is entered correctly, but
If you check in the onCreate function, the value is not assigned.
I want to use the recycler view by properly assigning a value
I tried to solve this problem, but my skills were not enough.
I desperately need the advice of seniors.
I would really appreciate it if you could show me a code sample if possible

Related

DiffUtil (dispatchUpdatesTo) not updating Recycler View

I am implementing a recycler view with diff util, but the first time I send the list to the adapter, the recycler view is not notified about the new list. Only the second time I update the list does the recycler receive the notification. I tried several solutions I found in similar questions but none worked. If anyone can help, thanks in advance.
Here is my code:
Adapter:
class UserListAdapter : Adapter<UserListItemViewHolder>() {
private var mUsers = mutableListOf<User>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserListItemViewHolder =
UserListItemViewHolder.create(parent)
override fun onBindViewHolder(holder: UserListItemViewHolder, position: Int) {
holder.bind(mUsers[position])
}
override fun getItemCount(): Int = mUsers.size
fun updateUsersList(users: List<User>) {
val diffCallback = UserListDiffCallback(this.mUsers, users)
val diffResult = DiffUtil.calculateDiff(diffCallback)
this.mUsers.clear()
this.mUsers.addAll(users)
diffResult.dispatchUpdatesTo(this)
}
}
UsersListDiffCallback:
class UserListDiffCallback(
private val oldList: List<User>,
private val newList: List<User>
) : DiffUtil.Callback() {
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition].username == newList[newItemPosition].username
}
override fun getOldListSize(): Int {
return oldList.size
}
override fun getNewListSize(): Int {
return newList.size
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return true
}
}
ViewModel:
#HiltViewModel
class MainViewModel #Inject constructor(
private val getUsersUseCase: GetUsersUseCase
) : ViewModel() {
private val _usersResultStatus = MutableLiveData<ResultStatus>(NotLoading)
val usersResultStatus: LiveData<ResultStatus>
get() = _usersResultStatus
private val _users = MutableLiveData<MutableList<User>?>()
val users: LiveData<MutableList<User>?>
get() = _users
fun getUsers() {
viewModelScope.launch {
try {
_usersResultStatus.value = Loading
_users.value = getUsersUseCase()
} catch (error: Throwable) {
_usersResultStatus.value = Error(error)
} finally {
_usersResultStatus.value = NotLoading
}
}
}
}
And where I update the list in the activity:
#AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private var _binding: ActivityMainBinding? = null
private val binding: ActivityMainBinding get() = _binding!!
private val viewModel: MainViewModel by viewModels()
private val usersAdapter = UserListAdapter()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
_binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
initUsersAdapter()
observeStates()
viewModel.getUsers()
}
private fun initUsersAdapter() {
with(binding.recyclerView) {
setHasFixedSize(true)
adapter = usersAdapter
}
}
private fun observeStates() {
viewModel.usersResultStatus.observe(this) { resultStatus ->
setProgressbarVisibility(resultStatus is Loading)
if (resultStatus is Error) {
Toast.makeText(
this#MainActivity,
getString(R.string.error),
Toast.LENGTH_SHORT
).show()
}
}
viewModel.users.observe(this) { users ->
users?.let {
usersAdapter.updateUsersList(users.toMutableList())
}
}
}
private fun setProgressbarVisibility(show: Boolean) {
binding.progressBar.visibility = if (show) View.VISIBLE else View.GONE
}
}
Trying to add item range changed to your code works like this for me
fun updateUsersList(users: List<User>) {
val diffCallback = UserListDiffCallback(this.mUsers, users)
val diffResult = DiffUtil.calculateDiff(diffCallback)
this.mUsers.clear()
this.mUsers.addAll(users)
diffResult.dispatchUpdatesTo(this)
notifyItemRangeChanged(0, users.size)
}

Problem with recyclerview last item added not showed inside a fragment

I having problem showing the last item when I update my recyclerview. The data is correct but I have to scroll down to show the last item because is out of screen. It's not a problem about constraint, nor margins, I've double checked it.I've read several posts here about how to fix it but none has worked for my code so far. Any suggestions?
This is my adapter:
class ComentarioAdaptador(private var context: Context, private var publicacionLista: ArrayList<Comentario>): RecyclerView.Adapter<ComentarioAdaptador.ViewHolder>()
{
private var tipoUsuario=""
class ViewHolder( itemView: View):RecyclerView.ViewHolder(itemView) {
var ivPerfil : ImageView = itemView.findViewById(R.id.iv_perfil)
var tvNombreUsuario: TextView = itemView.findViewById(R.id.tv_propietario)
var tvComentario: TextView = itemView.findViewById(R.id.tv_comentario)
var tvFecha: TextView = itemView.findViewById(R.id.tv_fecha)
var btnBorrar: Button =itemView.findViewById(R.id.brn_borrar_comentario)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view =LayoutInflater.from(context).inflate(R.layout.comentario,parent,false)
determinarTipoUsuario()
return ViewHolder(view)
}
override fun getItemCount(): Int {
return publicacionLista.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val comentario = publicacionLista[position]
holder.tvComentario.text =comentario.contenido
holder.tvFecha.text= comentario.fecha
buscarUsuario(holder.ivPerfil, holder.tvNombreUsuario, comentario.creadoPor,holder.btnBorrar)
holder.btnBorrar.setOnClickListener{
}
}
private fun buscarUsuario(ivPerfil: ImageView, tvNombreUsuario: TextView, propietario: String, btnBorrar:Button) {
val usuarioRef = FirebaseDatabase.getInstance().reference.child("Usuarios").child(propietario)
usuarioRef.addValueEventListener(object: ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
if (snapshot.exists()){
val usuario=snapshot.getValue(Usuario::class.java)
tvNombreUsuario.text=usuario!!.usuario
Glide.with(context).load(usuario.perfil).circleCrop().into(ivPerfil)
if (tipoUsuario=="usuario")
btnBorrar.isGone=true
else
btnBorrar.isVisible=true
}
}
override fun onCancelled(error: DatabaseError) {
}
})
}
private fun determinarTipoUsuario(){
val usuarioActual = FirebaseAuth.getInstance().currentUser!!
val userID = usuarioActual.uid
//LUEGO HAGO UNA INSTANCIA DE ESA UID
val busqueda = FirebaseDatabase.getInstance().getReference("Usuarios").child(userID)
//FINALMENTE LE PONGO UN LISTENER PARA GUARDAR DATOS
busqueda.addValueEventListener(object : ValueEventListener
{
override fun onDataChange(snapshot: DataSnapshot)
{
tipoUsuario = snapshot.getValue(Usuario::class.java)!!.tipo
Toast.makeText(context, tipoUsuario, Toast.LENGTH_SHORT).show()
}
override fun onCancelled(error: DatabaseError)
{}
})
}
}
This is how I call the the recyclerview on my fragment:
private fun mostrarComentarios(uidPostRecibido:String){
val comentariosRef= FirebaseDatabase.getInstance().reference.child("Comentarios").child(uidPostRecibido)
listaComentarios!!.clear()
comentariosRef.addValueEventListener(object : ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
if (snapshot.exists()){
for (snapshot in snapshot.children)
{
val comentario = snapshot.getValue(Comentario::class.java)
listaComentarios!!.add(comentario!!)
}
comentarioAdaptador!!.notifyDataSetChanged()
}
}
override fun onCancelled(error: DatabaseError) {
}
}
)
}

How to select and display a live table with kotlin, room, mvvm?

In my First fragment, I create the team name (corresponding to my team_table).
Then, I move on to the fragment for adding player names. I would like to display directly and only the list of players corresponding to the team. It seems to work when I want to update a player's name and come back to that player list. Otherwise, it shows me the list of all the players of all the teams. How can I do, please?
Here's my code:
class UserViewModel(application: Application): AndroidViewModel(application) {
val readAllDataTeam: LiveData<List<Team>>?
val readAllDataUser: LiveData<List<User>>?
val readAllDataEval: LiveData<List<Eval>>?
val readAllDataUserWithEval: LiveData<List<UserWithEval>>?
val readAllDataTeamWithUser: LiveData<List<TeamWithUser>>?
private val repositoryTeam: UserRepository
private val repositoryUser: UserRepository
private val repositoryEval: UserRepository
private val repositoryUserWithEval: UserRepository
private val repositoryTeamWithUser: UserRepository
init {
val teamDao = UserDatabase.getDatabase(application)?.userDao()
repositoryTeam = UserRepository(teamDao!!)
readAllDataTeam = repositoryTeam.readAllDataTeam
val userDao = UserDatabase.getDatabase(application)?.userDao()
repositoryUser = UserRepository(userDao!!)
readAllDataUser = repositoryUser.readAllDataUser
val evalDao = UserDatabase.getDatabase(application)?.userDao()
repositoryEval = UserRepository(evalDao!!)
readAllDataEval = repositoryEval.readAllDataEval
val userEvalDao = UserDatabase.getDatabase(application)?.userDao()
repositoryUserWithEval = UserRepository(userEvalDao!!)
readAllDataUserWithEval= repositoryUserWithEval.readAllDataUserEval
val teamUserDao = UserDatabase.getDatabase(application)?.userDao()
repositoryTeamWithUser = UserRepository(teamUserDao!!)
readAllDataTeamWithUser = repositoryTeamWithUser.readAllDataTeamWithUser
}
//Team
fun addTeam(team: Team) {
viewModelScope.launch(Dispatchers.IO) {
repositoryTeam.addTeam(team)
}
}
fun updateTeam(team: Team) {
viewModelScope.launch(Dispatchers.IO) {
repositoryTeam.updateTeam(team)
}
}
fun deleteTeam(team: Team) {
viewModelScope.launch(Dispatchers.IO) {
repositoryTeam.deleteTeam(team)
}
}
fun deleteAllTeams() {
viewModelScope.launch(Dispatchers.IO) {
repositoryTeam.deleteAllTeams()
}
}
//Eval
fun addEval(eval: Eval) {
viewModelScope.launch(Dispatchers.IO) {
repositoryEval.addEval(eval)
}
}
fun updateEval(eval: Eval) {
viewModelScope.launch(Dispatchers.IO) {
repositoryEval.updateEval(eval)
}
}
fun deleteEval(eval: Eval) {
viewModelScope.launch(Dispatchers.IO) {
repositoryEval.deleteEval(eval)
}
}
fun deleteAllEvals() {
viewModelScope.launch(Dispatchers.IO) {
repositoryEval.deleteAllEvals()
}
}
//User
fun addUser(user: User) {
viewModelScope.launch(Dispatchers.IO) {
repositoryUser.addUser(user)
}
}
fun updateUser(user: User) {
viewModelScope.launch(Dispatchers.IO) {
repositoryUser.updateUser(user)
}
}
fun deleteUser(user: User) {
viewModelScope.launch(Dispatchers.IO) {
repositoryUser.deleteUser(user)
}
}
fun deleteAllUsers() {
viewModelScope.launch(Dispatchers.IO) {
repositoryUser.deleteAllUsers()
}
}
fun searchDatabase(searchQuery: String): LiveData<List<User>>? {
return repositoryUser.searchDatabase(searchQuery)
}
fun searchDatabaseTeam(searchQuery: String): LiveData<List<Team>>? {
return repositoryUser.searchDatabaseTeam(searchQuery)
}
fun getTeam(searchTeam: String): LiveData<List<User>>? {
return repositoryUser.getTeam(searchTeam)
}
}
class UserRepository:
class UserRepository (private val userDao: UserDao) {
val readAllDataUser: LiveData<List<User>>? = userDao.getUserData()
val readAllDataEval: LiveData<List<Eval>>? = userDao.getEvalData()
val readAllDataTeam: LiveData<List<Team>>? = userDao.getTeamData()
val readAllDataUserEval: LiveData<List<UserWithEval>>? = userDao.getAllUserWithEval()
val readAllDataTeamWithUser: LiveData<List<TeamWithUser>>? = userDao.getAllTeamWithUser()
//User
suspend fun addUser(user: User) {
userDao.addUser(user)
}
suspend fun updateUser(user: User) {
userDao.updateUser(user)
}
suspend fun deleteUser(user: User) {
userDao.deleteUser(user)
}
suspend fun deleteAllUsers() {
userDao.deleteAllUsers()
}
//Eval
suspend fun addEval(eval: Eval) {
userDao.addEval(eval)
}
suspend fun updateEval(eval: Eval) {
userDao.updateEval(eval)
}
suspend fun deleteEval(eval: Eval) {
userDao.deleteEval(eval)
}
suspend fun deleteAllEvals() {
userDao.deleteAllEvals()
}
//Eval
suspend fun addTeam(team: Team) {
userDao.addTeam(team)
}
suspend fun updateTeam(team: Team) {
userDao.updateTeam(team)
}
suspend fun deleteTeam(team: Team) {
userDao.deleteTeam(team)
}
suspend fun deleteAllTeams() {
userDao.deleteAllTeams()
}
fun searchDatabase(searchQuery: String): LiveData<List<User>>? {
return userDao.searchDatabase(searchQuery)
}
fun searchDatabaseTeam(searchQuery: String): LiveData<List<Team>>? {
return userDao.searchDatabaseTeam(searchQuery)
}
fun getTeam(searchTeam: String): LiveData<List<User>>? {
return userDao.getTeam(searchTeam)
}
interface UserDao:
#Dao
interface UserDao {
#Query("SELECT * FROM user_table ORDER BY id ASC")
fun getUserData(): LiveData<List<User>>?
#Insert(onConflict = OnConflictStrategy.IGNORE)
fun addUser(user: User)
#Update
fun insertEval(eval: Eval)
#Update
fun updateUser(user: User)
#Delete
fun deleteUser(user: User)
#Query("DELETE FROM user_table")
fun deleteAllUsers()
#Query("SELECT * FROM user_table WHERE id=:id")
fun getOneUser(id: Int): User
#Transaction
#Query("SELECT * FROM user_table JOIN eval_table on user_table.id = eval_table.idEval ")
fun getAllUserWithEval(): LiveData<List<UserWithEval>>
#Query("SELECT * FROM user_table WHERE firstName LIKE :searchQuery OR lastName LIKE :searchQuery OR nbTeam LIKE :searchQuery OR nameTeam LIKE :searchQuery")
fun searchDatabase(searchQuery: String): LiveData<List<User>>?
#Query("SELECT * FROM team_table WHERE nameTeam LIKE :searchQuery")
fun searchDatabaseTeam(searchQuery: String): LiveData<List<Team>>?
#Transaction
#Query("SELECT * FROM user_table WHERE nameTeam LIKE :searchTeam")
fun getTeam(searchTeam: String): LiveData<List<User>>?
class ListFragment:
class ListFragment : Fragment(), SearchView.OnQueryTextListener {
//Pour accéder au fab
private var _binding: FragmentListBinding? = null
private val binding get() = _binding!!
private lateinit var mUserViewModel: UserViewModel
private val args by navArgs<ListFragmentArgs>()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
_binding = FragmentListBinding.inflate(inflater, container,false)
val view = binding.root
//Recyclerview pour affichier le custom row et les données
val adapter = ListAdapter()
val recyclerView = view.findViewById<RecyclerView>(R.id.recyclerview)
recyclerView?.adapter = adapter
recyclerView?.layoutManager = LinearLayoutManager(requireContext())
val searchTeam = args.currentTeam.nameTeam
binding.tvNameTeam.text = searchTeam
// UserViewModel pour afficher les données
mUserViewModel = ViewModelProvider(this).get(UserViewModel::class.java)
mUserViewModel.getTeam(searchTeam)?.observe(viewLifecycleOwner, Observer {
userT -> adapter.setData(userT)
})
/*
mUserViewModel.getTeam(args.currentTeam.nameTeam)
?.observe(viewLifecycleOwner, Observer { userT ->
adapter.setData(userT)
})
*/
binding.floatingActionButton.setOnClickListener{
findNavController().navigate(R.id.action_listFragment_to_addFragment)
}
// Add menu
setHasOptionsMenu(true)
return view
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.main_menu, menu)
inflater.inflate(R.menu.delete_menu, menu)
val search = menu?.findItem(R.id.menu_search)
val searchView = search?.actionView as? SearchView
searchView?.isSubmitButtonEnabled = true
searchView?.setOnQueryTextListener(this)
return
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.menu_delete){
deleteAllUsers()
}
return super.onOptionsItemSelected(item)
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
private fun deleteAllUsers() {
val builder = AlertDialog.Builder(requireContext())
builder.setPositiveButton("Yes"){ _, _ ->
mUserViewModel.deleteAllUsers()
Toast.makeText(
requireContext(),
"Suppression complète réussie",
Toast.LENGTH_SHORT).show()
}
builder.setNegativeButton("No"){_, _ -> }
builder.setTitle("Tout Supprimer?")
builder.setMessage("Êtes-vous sûr de vouloir supprimer l'ensemble des données?")
builder.create().show()
}
override fun onQueryTextSubmit(query: String?): Boolean {
return true
}
override fun onQueryTextChange(query: String?): Boolean {
if(query != null){
searchDatabase(query)
}
return true
}
private fun searchDatabase(query: String) {
val searchQuery = "%$query%"
val adapter = ListAdapter()
val recyclerView = view?.findViewById<RecyclerView>(R.id.recyclerview)
recyclerView?.adapter = adapter
recyclerView?.layoutManager = LinearLayoutManager(requireContext())
mUserViewModel.searchDatabase(searchQuery)?.observe(this, { userT->
userT.let {
adapter.setData(it)
}
})
}
}
class ListAdapter:
class ListAdapter : RecyclerView.Adapter<ListAdapter.MyViewHolder>() {
var userTList = emptyList<User>()
class MyViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) { }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.custom_row, parent, false))
}
override fun getItemCount(): Int {
return userTList.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val currentItemUT = userTList[position]
holder.itemView.findViewById<TextView>(R.id.id_txt).text = currentItemUT.id.toString()
holder.itemView.findViewById<TextView>(R.id.firstName_txt).text = currentItemUT.firstName
holder.itemView.findViewById<TextView>(R.id.lastName_txt).text = currentItemUT.lastName
holder.itemView.findViewById<TextView>(R.id.numeroTeam_txt).text = currentItemUT.nbTeam.toString()
holder.itemView.findViewById<View>(R.id.rowLayout).setOnClickListener {
val action = ListFragmentDirections.actionListFragmentToUpdateFragment(currentItemUT)
holder.itemView.findNavController().navigate(action)
}
holder.itemView.findViewById<Button>(R.id.btn_start_eval).setOnClickListener {
val action = ListFragmentDirections.actionListFragmentToEvalFragment(currentItemUT)
holder.itemView.findNavController().navigate(action)
}
}
fun setData(user: List<User>){
this.userTList = user
notifyDataSetChanged()
}
}

Two recycler view on same fragment, holder or db brings wrong data when I select item

Like title I can't get correct item data, now imagine I have 2 recycler view list on my main fragment, one recycler view is vertical, other horizontal. If I use only one recycler everything is working fine. But when I add other one it's opening items randomly, but that random data openings only random both recyclers positions. Like my first recycler have [a,b,c,d] , other recycler have [e,f,g,h]. When I click first item of first recycler its go to other fragment which shows detail, its opening e instead of a, if I go back and retry it, its opening e again, retry and its a !! so its opening randomly, why this is happening why can't I open correct data? I put Log.d on my adapters and when I click recycler items, adapters log says u clicked "a" but my detail fragment shows me data of "e". What I am doing wrong? Here is my codes:(I have lots of codes so I share what we need)
my databases TvDAO:
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import com.bt.filmdenemesi.model.Result
#Dao
interface TVDAO {
//Veri erişim nesnesi
#Insert
suspend fun insertAll(vararg movie: Result) : List<Long>
#Query("SELECT * FROM Result")
suspend fun getAllTV() : List<Result>
#Query("SELECT * FROM Result WHERE uuid2=:diziId")
suspend fun getTV(diziId:Int) : Result
#Query("DELETE FROM Result")
suspend fun deleteAllTV(
)
}
Tv Database:
#Database(entities = arrayOf(Result::class), version = 1)
abstract class TvDatabase: RoomDatabase() {
abstract fun tvDao(): TVDAO
companion object{
#Volatile
private var INSTANCE: TvDatabase?=null
fun databaseOlustur2(context: Context): TvDatabase {
return INSTANCE ?: synchronized(this){
val instance = Room.databaseBuilder(context.applicationContext,TvDatabase::class.java, "tvdatabase").fallbackToDestructiveMigration().build()
INSTANCE=instance
instance
}
}
}
}
movie Dao:
#Dao
interface MovieDAO {
//Veri erişim nesnesi
#Insert
suspend fun insertAll(vararg movie: Movie) : List<Long>
#Query("SELECT * FROM Movie")
suspend fun getAllMovie() : List<Movie>
#Query("Select * from Movie where uuid=:movieId")
suspend fun getMovie(movieId:Int) : Movie
#Query("Delete from Movie")
suspend fun deleteAllMovie(
)
}
movie database:
#Database(entities = arrayOf(Movie::class ), version = 1)
abstract class MovieDatabase:RoomDatabase() {
abstract fun movieDao(): MovieDAO
//singleton
companion object{
#Volatile private var instance: MovieDatabase? = null
private val lock = Any()
operator fun invoke(context: Context) = instance ?: synchronized(lock){
instance?: databaseOlustur(context).also {
instance = it
}
}
private fun databaseOlustur(context: Context)= Room.databaseBuilder(
context.applicationContext,
MovieDatabase::class.java,"moviedatabase").build()
}
}
my adapters:
class vizyonrecycleradapter(val diziListesi: ArrayList<Result>):RecyclerView.Adapter<vizyonrecycleradapter.DiziViewHolder>() {
class DiziViewHolder(itemview: View) : RecyclerView.ViewHolder(itemview)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DiziViewHolder {
val inflater = LayoutInflater.from(parent.context)
val view = inflater.inflate(R.layout.now_playing_recycler_row, parent, false)
return DiziViewHolder(view)
}
override fun onBindViewHolder(holder: DiziViewHolder, konum: Int) {
holder.itemView.tv_ismi.text=diziListesi.get(konum).name
val fotoDenemeleri = "https://image.tmdb.org/t/p/w500"
val fotobirlestirme: String = "${fotoDenemeleri}"+ diziListesi.get(konum).posterPath
holder.itemView.vizyon.gorselIndir(fotobirlestirme, placeHolderYap(holder.itemView.context))
holder.itemView.setOnClickListener {
val action2 = AnaSayfaDirections.actionAnaSayfaToDetaySayfasi(diziListesi[konum].uuid2)
Log.d("movie-title","${diziListesi.get(konum).originalName}")
Navigation.findNavController(it).navigate(action2)
}
}
override fun getItemCount(): Int {
return diziListesi.size
}
fun diziListesiniGuncelle(yeniDiziListesi: List<Result>) {
diziListesi.clear()
diziListesi.addAll(yeniDiziListesi)
notifyDataSetChanged()
}
}
other adapter:
class MovieRecyclerAdapter(val movieListesi: ArrayList<Movie>):RecyclerView.Adapter<MovieRecyclerAdapter.MovieViewHolder>() {
class MovieViewHolder(itemview: View) :RecyclerView.ViewHolder(itemview)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder {
val inflater = LayoutInflater.from(parent.context)
val view = inflater.inflate(R.layout.movie_recycler_row,parent,false)
return MovieViewHolder(view)
}
override fun onBindViewHolder(holder: MovieViewHolder, position: Int) {
holder.itemView.movieId.text= movieListesi.get(position).title
val fotoDenemeleri = "https://image.tmdb.org/t/p/w500"
val fotobirlestirme: String = "${fotoDenemeleri}"+movieListesi.get(position).backdropPath
holder.itemView.ana_foto.gorselIndir(fotobirlestirme, placeHolderYap(holder.itemView.context))
holder.itemView.setOnClickListener {
val action = AnaSayfaDirections.actionAnaSayfaToDetaySayfasi(movieListesi.get(position).uuid)
Log.d("movie-title","${movieListesi.get(position).title}")
Navigation.findNavController(it).navigate(action)
}
}
override fun getItemCount(): Int {
return movieListesi.size
}
fun movieListesiniGuncelle(yeniMovieListesi: List<Movie>){
movieListesi.clear()
movieListesi.addAll(yeniMovieListesi)
notifyDataSetChanged()
}
}
my base ViewModel:
open class BaseViewModel(application: Application) : AndroidViewModel(application),CoroutineScope {
private val job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
override fun onCleared() {
super.onCleared()
job.cancel()
}
}
detail ViewModel:
class MovieDetayiViewModel(application: Application): BaseViewModel(application) {
val diziLiveData = MutableLiveData<Result>()
val movieLiveData = MutableLiveData<Movie>()
val aramaLiveData = MutableLiveData<ResultX>()
fun roomVerisiniAl2(uuid2: Int){
launch {
val dao2=TvDatabase.databaseOlustur2(getApplication()).tvDao().getTV(uuid2)
//val dizi = dao.getTV(uuid2)
diziLiveData.value=dao2
}
}
fun roomVerisiniAl(uuid: Int){
launch {
val dao= MovieDatabase(getApplication()).movieDao().getMovie(uuid)
// val film = dao.getMovie(uuid)
movieLiveData.value=dao
}
}
fun roomVerisiniAl3(uuid3: Int){
launch {
val dao= AramaDatabase(getApplication()).aramaDao()
val arama = dao.getMovie(uuid3)
aramaLiveData.value=arama
}
}
}
movielistviewmvdel:
class MovieListesiViewModel(application: Application): BaseViewModel(application){
val filmler = MutableLiveData<List<Movie>>()
val dizi = MutableLiveData<List<Result>>()
val arama = MutableLiveData<List<ResultX>>()
val filmHataMesaji = MutableLiveData<Boolean>()
val filmYukleniyor = MutableLiveData<Boolean>()
private var guncellemeZamani = 1 * 60 * 1000 * 1000 * 1000L
private val filmApiServis = FilmAPIServis()
private val disposable = CompositeDisposable()
private val disposable2 = CompositeDisposable()
private val disposable3 = CompositeDisposable()//kullan at
private val ozelSharedPrefences = OzelSharedPrefences(getApplication())
fun refreshData(){
val kaydedilmeZamani = ozelSharedPrefences.zamaniAl()
if(kaydedilmeZamani != null && kaydedilmeZamani !=0L && System.nanoTime()-kaydedilmeZamani < guncellemeZamani){
verileriSQLitedenAl()
}else{
verileriInternettenAl()
}
}
fun refreshFromInternet(){
verileriInternettenAl()
}
private fun verileriSQLitedenAl(){
filmYukleniyor.value = true
launch {
val movieListesi = MovieDatabase(getApplication()).movieDao().getAllMovie()
movieleriGoster(movieListesi)
val diziListesi = TvDatabase.databaseOlustur2(getApplication()).tvDao().getAllTV()
tvleriGoster(diziListesi)
}
launch {
val aramaListesi = AramaDatabase(getApplication()).aramaDao().getAllMovie()
aramalariGoster(aramaListesi)
}
}
private fun verileriInternettenAl(){
filmYukleniyor.value = true
disposable.add(
filmApiServis.getData()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(object: DisposableSingleObserver<GetMoviesResponse>(){
override fun onSuccess(t: GetMoviesResponse) {
filmler.value= t.results
filmHataMesaji.value=false
filmYukleniyor.value=false
sqliteSakla(t.results)
// Toast.makeText(getApplication(),"Filmler internetten yüklendi",Toast.LENGTH_LONG).show()
}
override fun onError(e: Throwable) {
filmHataMesaji.value=true
filmYukleniyor.value=false
e.printStackTrace()
}
})
)
disposable2.add(
filmApiServis.getVizyondakiler()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(object: DisposableSingleObserver<NowPlaying>(){
override fun onSuccess(t: NowPlaying) {
dizi.value= t.results
filmHataMesaji.value=false
filmYukleniyor.value=false
diziSqLiteSakla(t.results)
}
override fun onError(e: Throwable) {
filmHataMesaji.value=true
filmYukleniyor.value=false
e.printStackTrace()
}
})
)
}
fun aramayiInternettenAl(denemeText:String){
disposable3.add(
filmApiServis.getArama(denemeText)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(object: DisposableSingleObserver<search>(){
override fun onSuccess(t: search) {
arama.value= t.results
aramaSqliteSakla(t.results)
}
override fun onError(e: Throwable) {
e.printStackTrace()
}
})
)
}
private fun movieleriGoster(filmlerListesi : List<Movie>?){
filmler.value= filmlerListesi
filmHataMesaji.value=false
filmYukleniyor.value=false
}
private fun tvleriGoster(tvListesi: List<Result>?){
dizi.value= tvListesi
filmHataMesaji.value=false
filmYukleniyor.value=false
}
private fun aramalariGoster(aramaListesi: List<ResultX>){
arama.value= aramaListesi
}
private fun sqliteSakla(filmListesi : List<Movie>){
launch {
val dao = MovieDatabase(getApplication()).movieDao()//dao içerisindeki fonksiyonlara ulaşmak için
dao.deleteAllMovie()
val uuidListesi = dao.insertAll(*filmListesi.toTypedArray())//tek tek movie haline getirmek için typed array. (*) koymak lazım
var i = 0
while (i < filmListesi.size){
filmListesi[i].uuid = uuidListesi[i].toInt()//uuid ye ulaştık modemdeki idleri eşledik
i = i + 1
}
movieleriGoster(filmListesi)
}
ozelSharedPrefences.zamaniKaydet(System.nanoTime())
}
private fun diziSqLiteSakla(diziListesi : List<Result>){
launch {
val dao2 = TvDatabase.databaseOlustur2(getApplication()).tvDao()//dao içerisindeki fonksiyonlara ulaşmak için
dao2.deleteAllTV()
val uuidListesi2 = dao2.insertAll(*diziListesi.toTypedArray())//tek tek movie haline getirmek için typed array. (*) koymak lazım
var i = 0
while (i < diziListesi.size){
diziListesi[i].uuid2 = uuidListesi2[i].toInt()//uuid ye ulaştık modemdeki idleri eşledik
i = i + 1
}
tvleriGoster(diziListesi)
}
ozelSharedPrefences.zamaniKaydet(System.nanoTime())
}
private fun aramaSqliteSakla(aramaListesi : List<ResultX>){
launch {
val dao = AramaDatabase(getApplication()).aramaDao()//dao içerisindeki fonksiyonlara ulaşmak için
dao.deleteAllMovie()
val uuidListesi3 = dao.insertAll(*aramaListesi.toTypedArray())//tek tek movie haline getirmek için typed array. (*) koymak lazım
var i = 0
while (i < aramaListesi.size){
aramaListesi[i].uuid3 = uuidListesi3[i].toInt()//uuid ye ulaştık modemdeki idleri eşledik
i = i + 1
}
arama.value?.let { aramalariGoster(it) }
}
ozelSharedPrefences.zamaniKaydet(System.nanoTime())
}
}
and this is my detail page fragment codes:
class DetaySayfasi : Fragment() {
private lateinit var viewModel : MovieDetayiViewModel
private lateinit var viewModel2: MovieListesiViewModel
var movieId : Int = 0
var getId : String =""
var listeIdAlma : Int = 0
private val ozelSharedPrefences2 = OzelSharedPrefences()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_detay_sayfa, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel2 = ViewModelProviders.of(this).get(MovieListesiViewModel::class.java)
viewModel2.refreshData()
arguments?.let {
movieId = DetaySayfasiArgs.fromBundle(it).movieID
}
viewModel = ViewModelProviders.of(this).get(MovieDetayiViewModel::class.java)
viewModel.roomVerisiniAl(movieId)
observeLiveData2()
viewModel.roomVerisiniAl2(movieId)
observeLiveData()
viewModel.roomVerisiniAl3(movieId)
dislike.setOnClickListener {
like()
}
like.setOnClickListener {
dislike()
}
observeLiveData3()
geri()
uygulamaPaylas()
}
fun observeLiveData(){
viewModel.movieLiveData.observe(viewLifecycleOwner, Observer { movie->
movie?.let {
getId = "movie/"+"${it.id}"
listeIdAlma= it.id
movie_title.text=it.title
movie_overview.text= it.overview
movie_rating_text.text=it.voteAverage.toFloat().toString()
movie_rating.rating = it.voteAverage.toFloat()/2
context?.let {
movie_backdrop.gorselIndir("https://image.tmdb.org/t/p/w500"+"${movie.backdropPath}", placeHolderYap(it))
movie_poster.gorselIndir("https://image.tmdb.org/t/p/w500"+"${movie.posterPath}", placeHolderYap(it))
}
if (!(listeIdAlma in ozelSharedPrefences2.korku())){
Log.d("ozelshared","${ozelSharedPrefences2.korku()}")
Log.d("listetaramaid","${listeIdAlma}")
like.visibility=View.GONE
dislike.visibility=View.VISIBLE
}else{
like.visibility=View.VISIBLE
dislike.visibility=View.GONE
Log.d("else","like kapalı olması lazım")
}
}
})
}
fun observeLiveData2(){
viewModel.diziLiveData.observe(viewLifecycleOwner, Observer { tv->
tv?.let {
getId = "tv/"+"${it.id}"
listeIdAlma = it.id
movie_title.text=it.name
movie_overview.text= it.overview
movie_rating_text.text= it.voteAverage?.toFloat().toString()
movie_rating.rating = it.voteAverage!!.toFloat()/2
context?.let {
movie_backdrop.gorselIndir("https://image.tmdb.org/t/p/w500"+"${tv.backdropPath}", placeHolderYap(it))
movie_poster.gorselIndir("https://image.tmdb.org/t/p/w500"+"${tv.posterPath}", placeHolderYap(it))
}
if (!(listeIdAlma in ozelSharedPrefences2.korku())){
Log.d("ozelshared","${ozelSharedPrefences2.korku()}")
Log.d("listetaramaid","${listeIdAlma}")
like.visibility=View.GONE
dislike.visibility=View.VISIBLE
}else{
like.visibility=View.VISIBLE
dislike.visibility=View.GONE
Log.d("else","like kapalı olması lazım")
}
}
})
}
fun observeLiveData3(){
viewModel.aramaLiveData.observe(viewLifecycleOwner, Observer { tv->
tv?.let {
if (it.voteAverage!=null){
getId = "tv/"+"${it.id}"
listeIdAlma = it.id!!
movie_title.text=it.name
movie_overview.text= it.overview
movie_rating_text.text= it.voteAverage?.toFloat().toString()
movie_rating.rating = it.voteAverage?.toFloat()!!/2
context?.let {
movie_backdrop.gorselIndir("https://image.tmdb.org/t/p/w500"+"${tv.backdropPath}", placeHolderYap(it))
movie_poster.gorselIndir("https://image.tmdb.org/t/p/w500"+"${tv.posterPath}", placeHolderYap(it))
}
}else{
getId = "tv/"+"${it.id}"
listeIdAlma = it.id!!
movie_title.text=it.name
movie_overview.text= it.name
movie_rating_text.text= ""
movie_rating.rating = 10F
context?.let {
movie_backdrop.gorselIndir("https://image.tmdb.org/t/p/w500"+"${tv.profile_path}", placeHolderYap(it))
movie_poster.gorselIndir("https://image.tmdb.org/t/p/w500"+"${tv.profile_path}", placeHolderYap(it))
}
}
if (!(listeIdAlma in ozelSharedPrefences2.korku())){
Log.d("ozelshared","${ozelSharedPrefences2.korku()}")
Log.d("listetaramaid","${listeIdAlma}")
like.visibility=View.GONE
dislike.visibility=View.VISIBLE
}else{
like.visibility=View.VISIBLE
dislike.visibility=View.GONE
Log.d("else","like kapalı olması lazım")
}
}
})
}
Like I said if I delete my one of recycler view its working perfect but if I use two recycler on same fragment I got wrong datas. Logs says I open correct data but it's not.
If u need my other codes to solve problem say it please I have lots of screens don't know which one I need to share to solve it.
i solved my problem but i don't know what i changed on background
i just seperate my one function to two function in MovieListesiViewmodel and gave a parameter and its worked like a miracle
private fun verileriInternettenAl(denemeInt: Int){
filmYukleniyor.value = true
disposable.add(
filmApiServis.getData(denemeInt)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(object: DisposableSingleObserver<GetMoviesResponse>(){
override fun onSuccess(t: GetMoviesResponse) {
filmler.value= t.results
filmHataMesaji.value=false
filmYukleniyor.value=false
sqliteSakla(t.results)
// Toast.makeText(getApplication(),"Filmler internetten yüklendi",Toast.LENGTH_LONG).show()
}
override fun onError(e: Throwable) {
filmHataMesaji.value=true
filmYukleniyor.value=false
e.printStackTrace()
}
})
)
}
fun verileriInternettenAl2(){
disposable2.add(
filmApiServis.getVizyondakiler()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(object: DisposableSingleObserver<NowPlaying>(){
override fun onSuccess(t: NowPlaying) {
dizi.value= t.results
filmHataMesaji.value=false
filmYukleniyor.value=false
diziSqLiteSakla(t.results)
}
override fun onError(e: Throwable) {
filmHataMesaji.value=true
filmYukleniyor.value=false
e.printStackTrace()
}
})
)
}

Parsing api using Retrofit and GSON

I'm parsing API and it's logging in the logcat, but I have a problem while retrieving it and using that data in a recycleview. These are my code snippets:
class MainActivity : AppCompatActivity() {
private val users = arrayListOf<User>()
private lateinit var adapter: RecyclerViewAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
init()
}
private fun init() {
adapter = RecyclerViewAdapter(users)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = adapter
val myViewModel : UsersViewModel by viewModel()
myViewModel.getAllUsers().observe(this, Observer {
users.add(it)
adapter.notifyDataSetChanged()
})
myViewModel.getUsers()
d("allUsers", users.size.toString())
}
}
I cannot set the data in a recyclerview, can anyone give me a hint? I could not find a proper source or code snippet to understand how I'm able to parse the data using a converter.
class UsersRequest {
private var retrofit = Retrofit.Builder()
.baseUrl("https://reqres.in/api/")
.addConverterFactory(ScalarsConverterFactory.create())
.build()
private var service = retrofit.create(ApiService::class.java)
interface ApiService {
#GET("users?page=1")
fun getRequest(): Call<String>
}
fun getRequest(callback: CustomCallback) {
val call = service.getRequest()
call.enqueue(onCallback(callback))
}
private fun onCallback(callback: CustomCallback): Callback<String> = object : Callback<String> {
override fun onFailure(call: Call<String>, t: Throwable) {
d("response", "${t.message}")
callback.onFailure(t.message.toString())
}
override fun onResponse(call: Call<String>, response: Response<String>) {
d("response", "${response.body()}")
callback.onSuccess(response.body().toString())
}
}
}
class RecyclerViewAdapter(private val users: ArrayList<User>) :
RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.user_layout,
parent,
false
)
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
return holder.onBind()
}
override fun getItemCount() = users.size
private lateinit var user:User
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun onBind() {
user = users[adapterPosition]
itemView.name.text = user.first_name
}
}
}
User(
val id: Int,
val email: String,
val first_name: String,
val last_name: String,
val avatar: String
)
with adapter class RecyclerViewAdapter(private val users: MutableList<User>) : RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>() { ...
Add this method to your adapter :
fun setUsers(usersList: List<User>) {
this.users.clear()
this.users.addAll(usersList)
notifyDataSetChanged()
}
and in MainActivity simply put :
myViewModel.getAllUsers().observe(this, Observer {
users -> hideLoading() // If you have a progress bar, here you can hide it
users?.let {
adapter.setUsers(users) }
})