I'm trying to follow MVVM pattern to fetch data from the given api but getting error while Initiating a connection. My application gets crashed showing the error in the logcat.
My ModalClass.kt
package com.example.retrofitdemo2.api
class ModelClass : ArrayList<ModelClassItem>()
ModelClassItem:
package com.example.retrofitdemo2.api
data class ModelClassItem(
val body: String,
val id: Int,
val title: String,
val userId: Int
)
RetrofitHelperClass.kt
package com.example.retrofitdemo2.api
import com.google.gson.GsonBuilder
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class RetrofitHelperClass {
companion object {
private val BASE_URL = "https://jsonplaceholder.typicode.com/"
var interceptor = HttpLoggingInterceptor().apply {
this.level = HttpLoggingInterceptor.Level.BODY
}
var client = OkHttpClient.Builder().apply {
this.addInterceptor(interceptor)
}.build()
fun getInstance(): Retrofit {
return Retrofit.Builder().baseUrl(BASE_URL).client(client)
.addConverterFactory(GsonConverterFactory.create(GsonBuilder().create())).build()
}
}
}
RetrofitService.kt
package com.example.retrofitdemo2.api
import androidx.lifecycle.LiveData
import retrofit2.Response
import retrofit2.http.GET
interface RetrofitService {
#GET("/albums")
fun get(): LiveData<Response<ModelClass>>
}
Repository.kt: Here i'm getting errors which is mentioned at the end.
Seems like repository is unable to create Adapter call.enter code here
package com.example.retrofitdemo2.repository
import com.example.retrofitdemo2.api.RetrofitService
class Repositroy(retrofitService: RetrofitService) {
val response = retrofitService.get()
}
viewmodel.kt:
package com.example.retrofitdemo2.viewmodel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.retrofitdemo2.api.ModelClass
import com.example.retrofitdemo2.api.ModelClassItem
import com.example.retrofitdemo2.repository.Repositroy
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class MainViewModel(repositroy: Repositroy) : ViewModel() {
var getdata = repositroy.response
}
MainViewModelFactory.kt:
package com.example.retrofitdemo2.viewmodel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.example.retrofitdemo2.repository.Repositroy
class MainViewModelFactory(private val repositroy: Repositroy) :
ViewModelProvider.Factory
{
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(MainViewModel::class.java)){
return MainViewModel(repositroy) as T
}
throw IllegalArgumentException("Problem in View Model Factory")
}
}
MainActivity.kt:
package com.example.retrofitdemo2
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.example.retrofitdemo2.api.RetrofitHelperClass
import com.example.retrofitdemo2.api.RetrofitService
import com.example.retrofitdemo2.databinding.ActivityMainBinding
import com.example.retrofitdemo2.repository.Repositroy
import com.example.retrofitdemo2.viewmodel.MainViewModel
import com.example.retrofitdemo2.viewmodel.MainViewModelFactory
import retrofit2.Retrofit
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var viewmodel : MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
var retorservice =
RetrofitHelperClass.getInstance().create(RetrofitService::class.java)
val repositroy = Repositroy(retorservice)
val factory = MainViewModelFactory(repositroy)
viewmodel = ViewModelProvider(this, factory).get(MainViewModel::class.java)
binding.viewmodel = viewmodel
binding.lifecycleOwner = this
viewmodel.getdata.observe(this, Observer {
Log.i("MainActivity", "${it}")
})
}
}
Error:
Unable to start activity
ComponentInfo{com.example.retrofitdemo2/com.example.retrofitdemo2.MainActivity}:
java.lang.IllegalArgumentException: Unable to create call adapter for
androidx.lifecycle.LiveData<retrofit2.Response<com.example.retrof
at com.example.retrofitdemo2.repository.Repositroy.<init>(Repositroy.kt:7)
at com.example.retrofitdemo2.MainActivity.onCreate(MainActivity.kt:28)
at android.app.Activity.performCreate(Activity.java:8109)
at android.app.Activity.performCreate(Activity.java:8083)
I have three activity activityA, activityB and activityC.
whenever we will start app it will launch activityA and based on shared preferences (based on boolean value which we will receive from shared preferences.) it will start activityB or activityC with onCreate Activity lifecycle event
here is my test code
package com.panther_nine.t2_mini
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import androidx.test.espresso.action.ViewActions.*
import androidx.test.espresso.assertion.ViewAssertions.*
import androidx.test.espresso.matcher.ViewMatchers.*
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import androidx.test.rule.ActivityTestRule
import com.panther_nine.t2_mini.database.sharedPref.dao.AppDao
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.*
import org.mockito.MockitoAnnotations
#LargeTest
#RunWith(AndroidJUnit4::class)
class ActivityATest {
#Mock
private lateinit var mPreferences: SharedPreferences
#Mock
private lateinit var mContext: Context
#get:Rule
val activityRule = ActivityTestRule(MainActivity::class.java, true, false)
#Before
fun setup(){
MockitoAnnotations.initMocks(this)
`when`(mContext.getSharedPreferences(anyString(), anyInt())).thenReturn(mPreferences)
}
#Test
fun testEvent() {
`when`(mPreferences.getBoolean(anyString(), anyBoolean())).thenReturn(false)
activityRule.launchActivity(Intent())
}
}
whenever I am launching my code sharedPreferences always returnning "true". it mean that mocking is not working
How to call api NotificationServiceExtension Android and similar in IOS ?
when notification is received i want to check the condition based on api call response
package com.example.app
import android.content.Context import com.onesignal.OSNotificationReceivedEvent import com.onesignal.OneSignal import android.app.Notification import android.R import androidx.core.app.NotificationCompat import android.content.SharedPreferences import android.util.Log
class NotificationServiceExtension : OneSignal.OSRemoteNotificationReceivedHandler {
override fun remoteNotificationReceived( context: Context,notificationReceivedEvent: OSNotificationReceivedEvent
) {
val notification = notificationReceivedEvent.notification
val mutableNotification = notification.mutableCopy()
//call api here and check condition
notificationReceivedEvent.complete(mutableNotification)
} }
I am a beginner to do the espresso test. I am using pressBack but it is not working it should return to the main activity from the second activity. The problem is that the press back is not working and due to this I get NoMatchingViewException. Can someone please help? I looked at different Solutions but I have not found an answer.
mport android.app.Activity
import android.app.Instrumentation
import android.content.Intent
import android.content.pm.ActivityInfo
import android.util.Log
import android.widget.TextView
import androidx.test.core.app.ActivityScenario
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.action.ViewActions.*
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.intent.Intents
import androidx.test.espresso.intent.matcher.IntentMatchers
import androidx.test.espresso.matcher.ViewMatchers.*
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
#LargeTest
#RunWith(AndroidJUnit4::class)
class MainActivityTest {
private var ivWeribeeZoo = 0
private var tvWeribeeName = 0
private var tvWeribeeRating = 0
private var ieWeribeeName = 0
private var etWeribeeRate = 0
private var ieDate = 0
#get:Rule
var activityRule: ActivityScenarioRule<MainActivity>
= ActivityScenarioRule(MainActivity::class.java)
#Before
fun setUP()
{
ivWeribeeZoo = R.id.ivWeribeeZoo
tvWeribeeName = R.id.tvZooName
tvWeribeeRating = R.id.suRating
ieWeribeeName = R.id.itName
etWeribeeRate = R.id.etRating
ieDate = R.id.itDate
}
#Test
fun nameInMainMatchesNewName() {
//val activityScenario = ActivityScenario.launch(MainActivity::class.java)
onView(withId(ivWeribeeZoo)).perform(click())
onView(withId(ieWeribeeName)).perform(clearText(), typeText("ZOO"))
closeSoftKeyboard()
/* val mDevice:UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mDevice.pressBack()*/
onView(isRoot()).perform(pressBack())
onView(withId(tvWeribeeName)).check(matches(withText("ZOO")))
}
I'm trying to learn Hilt and am getting the error "Dagger does not support injection into private fields". But the field in question isn't private in the original Kotlin. It's only private when it's converted to Java. Why is this? How can I correct it?
Original Kotlin file:
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.example.vennwithnav.databinding.FragmentLoginBinding
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
#AndroidEntryPoint
class LoginFragment : Fragment() {
#Inject public var profileViewModel: ProfileViewModel? = null
private var binding: FragmentLoginBinding? = null
Java file after conversion (accessed via the error):
package com.example.vennwithnav.ui.profile;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.example.vennwithnav.databinding.FragmentLoginBinding;
import dagger.hilt.android.AndroidEntryPoint;
import javax.inject.Inject;
#kotlin.Metadata(mv = {1, 4, 1}, bv = {1, 0, 3}, k = 1, d1 = {"\u0000:\n\u0002\u0018\u0002\n\u0002\u0018\u0002\n\u0002\b\u0002\n\u0002\u0018\u0002\n\u0000\n\u0002\u0018\u0002\n\u0002\b\u0005\n\u0002\u0010\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\n\u0002\u0018\u0002\n\u0002\b\u0002\b\u0007\u0018\u00002\u00020\u0001B\u0005\u00a2\u0006\u0002\u0010\u0002J\u0006\u0010\u000b\u001a\u00020\fJ&\u0010\r\u001a\u0004\u0018\u00010\u000e2\u0006\u0010\u000f\u001a\u00020\u00102\b\u0010\u0011\u001a\u0004\u0018\u00010\u00122\b\u0010\u0013\u001a\u0004\u0018\u00010\u0014H\u0016J\b\u0010\u0015\u001a\u00020\fH\u0016R\u0010\u0010\u0003\u001a\u0004\u0018\u00010\u0004X\u0082\u000e\u00a2\u0006\u0002\n\u0000R\u001a\u0010\u0005\u001a\u00020\u0006X\u0086\u000e\u00a2\u0006\u000e\n\u0000\u001a\u0004\b\u0007\u0010\b\"\u0004\b\t\u0010\n\u00a8\u0006\u0016"}, d2 = {"Lcom/example/vennwithnav/ui/profile/LoginFragment;", "Landroidx/fragment/app/Fragment;", "()V", "binding", "Lcom/example/vennwithnav/databinding/FragmentLoginBinding;", "profileViewModel", "Lcom/example/vennwithnav/ui/profile/ProfileViewModel;", "getProfileViewModel", "()Lcom/example/vennwithnav/ui/profile/ProfileViewModel;", "setProfileViewModel", "(Lcom/example/vennwithnav/ui/profile/ProfileViewModel;)V", "login", "", "onCreateView", "Landroid/view/View;", "inflater", "Landroid/view/LayoutInflater;", "container", "Landroid/view/ViewGroup;", "savedInstanceState", "Landroid/os/Bundle;", "onDestroyView", "app_debug"})
#dagger.hilt.android.AndroidEntryPoint()
public final class LoginFragment extends androidx.fragment.app.Fragment {
#org.jetbrains.annotations.NotNull()
private com.example.vennwithnav.ui.profile.ProfileViewModel profileViewModel; // this line is causing the error
private com.example.vennwithnav.databinding.FragmentLoginBinding binding;
#org.jetbrains.annotations.NotNull()
public final com.example.vennwithnav.ui.profile.ProfileViewModel getProfileViewModel() {
return null;
}
public final void setProfileViewModel(#org.jetbrains.annotations.NotNull()
com.example.vennwithnav.ui.profile.ProfileViewModel p0) {
}
One more google search found the answer. https://kotlinlang.org/docs/java-to-kotlin-interop.html#instance-fields
Adding #JvmField in front of var fixed the problem.
#Inject #JvmField var profileViewModel: ProfileViewModel? = null
per IR42, this works too, and is the used in the developer.android.com tutorials, so it's probably better.
#Inject lateinit var profileViewModel: ProfileViewModel