NetworkOnMainThreadException with Retrofit and Rxandroid in kotlin - kotlin

This question has asked many times but none of the solutions is working. I don't know what's going on with code. Always shows android.os.NetworkOnMainThreadException
Below code is my ViewModel class
class MainActicityViewModel(val context: MainActivity) : BaseObservable() {
val layoutManagerAppointment = LinearLayoutManager(context)
private val appClient = Appclient().getClient(context)
private val apiInterface = appClient.create(ApiInterface::class.java)
var rcyAdapter: RcyAdapter? = null
init {
getList()
}
fun getList() {
val observable = apiInterface.getUsers()
observable.subscribeOn(Schedulers.io()) // i have also registerd for Schedulers.newThread()
observable.observeOn(AndroidSchedulers.mainThread())
observable.subscribeWith(object : DisposableObserver<ArrayList<Data>>() {
override fun onComplete() {
Toast.makeText(context, "onComplete", Toast.LENGTH_SHORT).show()
}
override fun onNext(t: ArrayList<Data>) {
Log.e("SIZE", "" + t.size)
Toast.makeText(context, "onNext", Toast.LENGTH_SHORT).show()
}
override fun onError(e: Throwable) {
Toast.makeText(context, "onError", Toast.LENGTH_SHORT).show()
Log.e("TAG ON ERROR", "" + e)
}
})
}
}
Below code is Retrofit Client class
class Appclient {
private var retrofit: Retrofit? = null
private val baseUrl = "https://jsonplaceholder.typicode.com"
fun getClient(context: Context): Retrofit {
//Here a logging interceptor is created
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient.Builder()
.addInterceptor(interceptor).build()
retrofit = Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(client)
.build()
return (retrofit)!!
}}
And my retrofit interface
interface ApiInterface {
#GET("/users")
fun getUsers(): Observable<ArrayList<Data>>}
Here is the MainActivity class
class MainActivity : AppCompatActivity() {
lateinit var vModel: MainActicityViewModel
var mainBinding: ActivityMainBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mainBinding = DataBindingUtil.setContentView(this#MainActivity, R.layout.activity_main)
vModel = MainActicityViewModel(this#MainActivity)
mainBinding!!.viewModel = vModel
}}

Try this...
fun getList() {
val observable:Observable<ArrayList<Data>> = apiInterface.getUsers()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(object : DisposableObserver<ArrayList<Data>>() {
override fun onComplete() {
Toast.makeText(context, "onComplete", Toast.LENGTH_SHORT).show()
}
override fun onNext(t: ArrayList<Data>) {
Log.e("SIZE", "" + t.size)
Toast.makeText(context, "onNext", Toast.LENGTH_SHORT).show()
}
override fun onError(e: Throwable) {
Toast.makeText(context, "onError", Toast.LENGTH_SHORT).show()
Log.e("TAG ON ERROR", "" + e)
}
})
}
Observable needs to be chain calls when you do RxJava operations because Observable is not the builder pattern.

Related

Can't log any data from API call

I'm pretty new to kotlin, and I feel pretty much overwhelmed by it. I'd like to ask - how I can display any data from MutableLiveData? I've tried to Log it, but it doesn't seem to work. I've already added the internet permission to the manifest. Here's the code:
ApiServices
interface ApiServices {
#GET("/fixer/latest/")
fun getRatesData(
#Query("base") base: String,
#Query("apikey") apikey: String
): Call<CurrencyModel>
companion object {
private const val url = "https://api.apilayer.com/"
var apiServices: ApiServices? = null
fun getInstance(): ApiServices {
if (apiServices == null) {
val retrofit = Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build()
apiServices = retrofit.create(ApiServices::class.java)
}
return apiServices!!
}
}
}
Repository
class CurrencyRepository constructor(private val apiServices: ApiServices) {
fun getLatestRates() = apiServices.getRatesData("EUR", "API_KEY");
}
ViewModel
class CurrencyViewModel constructor(private val currencyRepository: CurrencyRepository) :
ViewModel() {
val currencyRatesList = MutableLiveData<CurrencyModel>()
val errorMessage = MutableLiveData<String>()
fun getLatestRates() {
val response = currencyRepository.getLatestRates();
response.enqueue(object : retrofit2.Callback<CurrencyModel> {
override fun onResponse(
call: retrofit2.Call<CurrencyModel>,
response: Response<CurrencyModel>
) {
currencyRatesList.postValue(response.body())
}
override fun onFailure(call: retrofit2.Call<CurrencyModel>, t: Throwable) {
errorMessage.postValue(t.message)
}
})
}
}
FactoryViewModel
class CurrencyViewModelFactory constructor(private val repository: CurrencyRepository) :
ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return if (modelClass.isAssignableFrom(CurrencyViewModel::class.java)) {
CurrencyViewModel(this.repository) as T
}else{
throw IllegalArgumentException("Couldn't found ViewModel")
}
}
}
MainActivity
class MainActivity : AppCompatActivity() {
private val retrofitService = ApiServices.getInstance()
lateinit var viewModel: CurrencyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this, CurrencyViewModelFactory(CurrencyRepository(retrofitService)))
.get(CurrencyViewModel::class.java)
viewModel.currencyRatesList.observe(this, Observer {
Log.d(TAG, "onCreate: $it")
})
viewModel.errorMessage.observe(this, Observer {
viewModel.getLatestRates()
})
}
}
You never call viewModel.getLatestRates() in your onCreate() to fetch an initial value for your LiveData, so it never emits anything to observe. The only place you have called it is inside your error listener, which won't be called until a fetch returns an error.
Side note, I recommend naming the function "fetchLatestRates()". By convention, "get" implies that the function returns what it's getting immediately rather than passing it to a LiveData later when its ready.
And a tip. Instead of this:
class MainActivity : AppCompatActivity() {
lateinit var viewModel: CurrencyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ...
viewModel = ViewModelProvider(this, CurrencyViewModelFactory(CurrencyRepository(retrofitService)))
.get(CurrencyViewModel::class.java)
//...
}
}
You can do this for the same result:
class MainActivity : AppCompatActivity() {
val viewModel: CurrencyViewModel by viewModels(CurrencyViewModelFactory(CurrencyRepository(retrofitService)))
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ...
}
}

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

How can i to show the Ad when i push the button for next activity?

class MainActivity : AppCompatActivity() {
lateinit var mAdView : AdView
private var mInterstitialAd: InterstitialAd? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
loadBannerAd()
loadInterAd()
val wLista = findViewById<Button>(R.id.Lista)
wLista.setOnClickListener{
showInterAd()
startActivity(Intent(this, com.tango.changapp.wLista::class.java))
}
private fun showInterAd() {
if(mInterstitialAd != null){
mInterstitialAd?.fullScreenContentCallback = object : FullScreenContentCallback(){
override fun onAdFailedToShowFullScreenContent(p0: AdError) {
super.onAdFailedToShowFullScreenContent(p0)
}
override fun onAdShowedFullScreenContent() {
super.onAdShowedFullScreenContent()
}
override fun onAdDismissedFullScreenContent() {
super.onAdDismissedFullScreenContent()
val intent = Intent(this#MainActivity, MainActivity::class.java)
startActivity(intent)
}
override fun onAdImpression() {
super.onAdImpression()
}
}
mInterstitialAd?.show(this)
}else{
val intent = Intent(this, MainActivity2::class.java)
//startActivity(intent)
}
}
private fun loadInterAd() {
var adRequest = AdRequest.Builder().build()
InterstitialAd.load(this,"ca-app-pub-3940256099942544/1033173712", adRequest, object : InterstitialAdLoadCallback() {
override fun onAdFailedToLoad(adError: LoadAdError) {
mInterstitialAd = null
}
override fun onAdLoaded(interstitialAd: InterstitialAd) {
mInterstitialAd = interstitialAd
}
})
}
I have the following code, and I want for an Ad to be launched when I advance to the next activity, but it doesn't happen, the Ad is only launched when I am in the other activity and I press the return button

compare room database valuw with user input

How can I compare the value from the room database with the text field? I want to compare the user input value with the credential view model but I have no idea how to do it. I have already set the query in the credentialDao so the value fetched should be inside the view model. But I just could not compare it.
CredentialDao
#Dao
interface CredentialDao {
//if user name same ignore
#Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun addUser(credential: Credential)
#Update
suspend fun updateUser(credential: Credential)
#Query("SELECT * FROM credential_table WHERE userName LIKE :userName AND password LIKE :password")
fun readAllData(userName: String, password: String): Credential
}
CredentialDatabase
#Database(entities = [Credential::class], version = 1, exportSchema = false)
#TypeConverters(dateConverter::class)
abstract class CredentialDatabase: RoomDatabase() {
abstract fun credentialDao(): CredentialDao
companion object{
#Volatile
private var INSTANCE: CredentialDatabase? = null
val migration_1_2: Migration = object: Migration(2,1){
override fun migrate(database: SupportSQLiteDatabase){
}
}
fun getDatabase(context: Context): CredentialDatabase{
val tempInstance = INSTANCE
if(tempInstance != null){
return tempInstance
}
synchronized(this){
val instance = Room.databaseBuilder(
context.applicationContext,
CredentialDatabase::class.java,
"credential_database"
).fallbackToDestructiveMigration()
.build()
INSTANCE = instance
return instance
}
}
}
}
Credential Repository
class CredentialRepository(private val credentialDao: CredentialDao) {
suspend fun addCredential(credential: Credential){
credentialDao.addUser(credential)
}
suspend fun updateCredential(credential: Credential){
credentialDao.updateUser(credential)
}
fun readAllData(username: String,password:String) {
credentialDao.readAllData(username,password)
}
}
CredentialViewModel
class CredentialViewModel(application: Application): AndroidViewModel(application) {
private val repository: CredentialRepository
init{
val credentialDao = CredentialDatabase.getDatabase(application).credentialDao()
repository = CredentialRepository(credentialDao)
}
fun addCredential(credential: Credential){
viewModelScope.launch(Dispatchers.IO){
repository.addCredential(credential)
}
}
fun updateCredential(credential: Credential){
viewModelScope.launch(Dispatchers.IO){
repository.updateCredential(credential)
}
}
fun readAllData(userName: String, password: String){
viewModelScope.launch(Dispatchers.IO){
repository.readAllData(userName, password)
}
}
}
LoginActivity
class LoginActivity : AppCompatActivity() {
private lateinit var mUserViewModel: CredentialViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
// Inflate the layout for this fragment
mUserViewModel = ViewModelProvider(this).get(CredentialViewModel::class.java)
val login = findViewById<Button>(R.id.login_btn)
login?.setOnClickListener {
val userName = username_txt.text.toString().trim();
val password = password_txt.text.toString().trim();
if(userName.isEmpty()||password.isEmpty()){
Toast.makeText(
applicationContext,
"Please fill out all field!",
Toast.LENGTH_SHORT
).show()
}else{
mUserViewModel.readAllData(userName, password)
if(user!=null){
Toast.makeText(applicationContext, "Successfully Login!", Toast.LENGTH_SHORT).show()
val intent = Intent(this#LoginActivity, MainActivity::class.java)
intent.putExtra("Username",userName)
startActivity(intent)
}else{
Toast.makeText(applicationContext, "Wrong Password!", Toast.LENGTH_SHORT).show()
}
}
}
}
}
I think the readAllData() method in your CredentialRepository is incorrect, because this function needs to return the query result to CredentialViewModel. Your correct approach is to pass the query result to ViewModel.
When trying to log in, you should also call the method defined in ViewModel and pass username and password to this method for retrieval. The final result defines a LiveData<Boolean> to represent whether you log in successfully.
class CredentialViewModel(application: Application): AndroidViewModel(application) {
private val mResult = MutableLiveData<Credential>()
val resultLiveData: LiveData<Credential> get() = mResult
private val repository: CredentialRepository
init{
val credentialDao = CredentialDatabase.getDatabase(application).credentialDao()
repository = CredentialRepository(credentialDao)
}
fun addCredential(credential: Credential){
viewModelScope.launch(Dispatchers.IO){
repository.addCredential(credential)
}
}
fun updateCredential(credential: Credential){
viewModelScope.launch(Dispatchers.IO){
repository.updateCredential(credential)
}
}
fun readAllData(userName: String, password: String){
viewModelScope.launch(Dispatchers.IO){
mResult.postValue(repository.readAllData(userName, password))
}
}
}
class LoginActivity : AppCompatActivity() {
private lateinit var mUserViewModel: CredentialViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
// Inflate the layout for this fragment
mUserViewModel = ViewModelProvider(this).get(CredentialViewModel::class.java)
val login = findViewById<Button>(R.id.login_btn)
mUserViewModel.resultLiveData.observe(this#LoginActivity, { credential ->
if(credential!=null){
Toast.makeText(applicationContext, "Successfully Login!", Toast.LENGTH_SHORT).show()
val intent = Intent(this#LoginActivity, MainActivity::class.java)
intent.putExtra("Username",userName)
startActivity(intent)
}else{
Toast.makeText(applicationContext, "Wrong Password!", Toast.LENGTH_SHORT).show()
}
})
login?.setOnClickListener {
val userName = username_txt.text.toString().trim();
val password = password_txt.text.toString().trim();
if (userName.isEmpty() || password.isEmpty()) {
Toast.makeText(
applicationContext,
"Please fill out all field!",
Toast.LENGTH_SHORT
).show()
} else {
mUserViewModel.readAllData(userName, password)
}
}
}
}
modify Repository
class CredentialRepository(private val credentialDao: CredentialDao) {
suspend fun addCredential(credential: Credential){
credentialDao.addUser(credential)
}
suspend fun updateCredential(credential: Credential){
credentialDao.updateUser(credential)
}
fun readAllData(username: String,password:String) :Credential{
return credentialDao.readAllData(username,password)
}
}

why it doesn't send any request to server?

my project is based on clean architecture and hilt
I'm trying to request some data from a Web Service which I made with Python.
I don't know why but it doesn't receive any request from app
my apiservice
interface Service {
#GET("/question")
fun getQuestion(): Single<Question>
my apimodule
class ApiModule {
#Provides
#Singleton
fun provideOkHttpClient(): OkHttpClient {
val okHttpBuilder = OkHttpClient.Builder()
okHttpBuilder.addInterceptor(HttpLoggingInterceptor())
return okHttpBuilder.build()
}
#Provides
#Singleton
fun provideGson(): Gson {
return GsonBuilder()
.setLenient()
.create()
}
#Provides
#Singleton
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(" http://25ae1464a63a.ngrok.io")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.client(okHttpClient)
.build()
}
#Provides
#Singleton
fun bindApiService(retrofit: Retrofit): Service {
return retrofit.create(Service::class.java)
my viewmodel
class MainViewModel #ViewModelInject constructor(
private val questionUseCaseImpl: QuestionUseCaseImpl,
): ViewModel(){
val questionModel = MutableLiveData<QuestionModel>()
private val compositeDisposable = CompositeDisposable()
fun getData() {
questionUseCaseImpl.execute()
.subscribeOn(Schedulers.io())
.subscribe({
it?.let {
questionModel.postValue(it)
}
},{
}).let {
compositeDisposable.add(it)
}
}
override fun onCleared() {
compositeDisposable.clear()
}
}
my main activity
class MainActivity : AppCompatActivity() {
private val mainViewModel by viewModels<MainViewModel> ()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button: Button = findViewById(R.id.startButton)
button.setOnClickListener {
mainViewModel.getData()
}
mainViewModel.questionModel.observe(this, {
it?.let {
Toast.makeText(
this,
"${it.first}is ${it.second}",
Toast.LENGTH_LONG
).show()
}
})
}
And I have no response at all! In logs it seems like I haven't sent any request