I am trying to learn Jetpack benchmark. By reviewing this google sample : https://github.com/android/performance-samples/tree/main/MacrobenchmarkSample
One of classes includes following method :
private fun MacrobenchmarkScope.clickOnId(resourceId: String) {
val selector = By.res(packageName, resourceId)
if (!device.wait(Until.hasObject(selector), 2_500)) {
fail("Did not find object with id $resourceId")
}
device
.findObject(selector)
.click()
// Chill to ensure we capture the end of the click span in the trace.
Thread.sleep(100)
}
And it has been called like : clickOnId("launchRecyclerActivity")
The string is a resource :
<string name="launchRecyclerActivity">RecyclerView</string>
And RecyclerView is an item in MainActivity :
BenchmarkActivityButton(name = "RecyclerView") {
launchActivityWithTrace<NonExportedRecyclerActivity>()
}
#Composable
fun BenchmarkActivityButton(name: String, onClick: () -> Unit) {
TextButton(
modifier = Modifier.padding(8.dp),
onClick = onClick,
border = BorderStroke(1.dp, MaterialTheme.colors.primary)
) {
Text(name)
}
}
The problem is this line returns null : val selector = By.res(packageName, resourceId)
And therefore I receive following exception :
java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.test.uiautomator.UiObject2.click()' on a null object reference
at com.example.macrobenchmark.clickslatency.ClickLatencyBenchmark.clickOnId(ClickLatencyBenchmark.kt:189)
at com.example.macrobenchmark.clickslatency.ClickLatencyBenchmark.access$clickOnId(ClickLatencyBenchmark.kt:40)
at com.example.macrobenchmark.clickslatency.ClickLatencyBenchmark$simpleViewClick$2.invoke(ClickLatencyBenchmark.kt:64)
at com.example.macrobenchmark.clickslatency.ClickLatencyBenchmark$simpleViewClick$2.invoke(ClickLatencyBenchmark.kt:51)
at androidx.benchmark.macro.MacrobenchmarkKt$macrobenchmark$measurements$1$tracePath$1.invoke(Macrobenchmark.kt:193)
at androidx.benchmark.macro.MacrobenchmarkKt$macrobenchmark$measurements$1$tracePath$1.invoke(Macrobenchmark.kt:167)
at androidx.benchmark.perfetto.PerfettoCaptureWrapper.record(PerfettoCaptureWrapper.kt:90)
at androidx.benchmark.macro.MacrobenchmarkKt.macrobenchmark(Macrobenchmark.kt:167)
at androidx.benchmark.macro.MacrobenchmarkKt.macrobenchmarkWithStartupMode(Macrobenchmark.kt:301)
at androidx.benchmark.macro.junit4.MacrobenchmarkRule.measureRepeated(MacrobenchmarkRule.kt:106)
at com.example.macrobenchmark.clickslatency.ClickLatencyBenchmark.simpleViewClick(ClickLatencyBenchmark.kt:51)
How it can be resolved?
Related
I used the following function in my code:
private fun sharedPreferences() = context.getSharedPreferences(
"sunny_weather",
Context.MODE_PRIVATE
)
fun getSavedPlace(): Place {
val placeJson = sharedPreferences().getString("place","")
return Gson().fromJson(placeJson, Place::class.java)
}
but the following error appear
java.lang.NullPointerException: Gson().fromJson(placeJson, Place::class.java) must not be null
i had found a similar question and according to asker's meaning, although his code isn`t similar to mine, he also write the getString function but set the second parameter to null. so his program went wrong, and after changing, his program ran well. but i had set the parameter to "", not null, but it's wrong.
Use "{}" for the default value:
fun getSavedPlace(): Place {
val placeJson = sharedPreferences().getString("place","{}")
return Gson().fromJson(placeJson, Place::class.java)
}
I am trying to invoke a method with argument received as an argument but not able to do so. Here is what I am trying.
I have a method which gets me alert dialog object like below.
fun getAlertDialog(
title: String,
positiveButtonText: String,
positiveClickAction: (() -> Unit)) {
someTextView.setOnClickListener {
positiveClickActin.invoke()
}
and the above can be called like below
val dialog = getAlertDialog("Title", "Ok", ::clickedOk)
considering clickedOk is a void method like below
fun clickedOk() {
println("clicked")
}
But I am stuck when i want to pass a method with argument. Let's say I want to print some variable. The getSimpleDialog method can be changed as below.
fun getAlertDialog(
title: String,
positiveButtonText: String,
positiveClickAction: ((any: Any) -> Unit))
someTextView.setOnClickListener {
positiveClickActin.invoke() //this cannot be achieved now as the method takes an argument
}
and call it as
val dialog = getSimpleDialog("Hello", "ok", { variable -> println("clicked $variable")})
but i cannot invoke this method in the getSimpleDialog's on click listener. How do I achieve it?
You can either call
positiveClickActin.invoke(param)
or simply,
positiveClickActin(param)
Similarly for no parameter case you can use
positiveClickActin()
Instead of calling invoke().
While reading in the doc, the invoke() looks to be useful while having mixed of java and kotlin code. (but I might be wrong here as I am still new in kotlin)
I have the following in my viewmodel :
// hold the list of comments of a Post
private val _commentsOfPost = MutableLiveData<PagedList<Comment>>()
val commentsOfPost : LiveData<PagedList<Comment>> = _commentsOfPost
fun getCommentsOfPost(postId: Long){
_commentsOfPost.value = commentRepository.getCommentsOfPost(postId) // <--- TYPE MISMATCH
}
So, what happens is that whenever the getCommentsOfPost() is called by the Fragment, it retrieves a PagedList of Comment instances belonging to a Post specified by its ID.
But Android tells me about a Type mismatch ( see the arrow in the codesnippet above):
Required: PagedList<Comment>?
Found: LiveData<PagedList<Comment>>
For the sake of completeness, this is the getCommentsOfPost() interface:
fun getCommentsOfPost(postId: Long) : LiveData<PagedList<Comment>>
How can I change it so that this error disappears ?
You should return to PagedList,
sample:
fun getCommentsOfPost(postId: Long) : PagedList<Comment> {
// your code
// return PagedList<Comment>
}
before the code as follows
class MainAdapter(val locationList: ArrayList<HashMap<String,String>>): RecyclerView.Adapter<MainAdapter.ViewHolder>() {
val byDates = locationList.groupBy { it["time"] } //this fine
}
after that i change to use model
class MainAdapter(val locationList: ArrayList<Model>): RecyclerView.Adapter<MainAdapter.ViewHolder>() {
val byDates = locationList.groupBy { it["time"] } //this red line i cant resolve
}
and this my model
data class Model(val name : String?,
val address : String?,
val time : String?)
It's because in the first (working) example it refers to an instance of HashMap<String, String>, thus calling it["time"] is actually equal to calling it.get("time").
In the second example however, it refers to Model. In Kotlin, you cannot access properties by "brackets" syntax (like in JS for example), thus it shows an error. The correct code would be locationList.groupBy { it.time }.
I have a "insert_data()" function in same class with RecyleView's adapter class. With this method, I'll populate an array.
That method works after clicking an "setOnClickListener".
So onBindViewHolder method's codes are below,
override fun onBindViewHolder(holder: adsViewHolder, position: Int) {
holder.itemView.txt_ads.text = category[position]
holder.itemView.setOnClickListener(){
if (holder.itemView.txt_ads.text.contains("Estate")){
var arrayID = holder.itemView.resources.getIdentifier("EstateCategory","array", holder.itemView.context.packageName )
var category_arraylist = ArrayList<String>(9)
i**nsert_data(category_arraylist,arrayID)**
var mylinearlayout = LinearLayoutManager(holder.itemView.context,LinearLayoutManager.VERTICAL, false)
holder.itemView.myAdsRecycleView.layoutManager = mylinearlayout
var myadapter = adsRecyleAdapter(category_arraylist)
holder.itemView.myAdsRecycleView.adapter = myadapter
}
}
}
and "insert_data()" method's codes are below,
fun insert_data(categoryArraylist: ArrayList<String>,arrayID:Int) {
var obje = AppCompatActivity()
var Category = obje.resources.getStringArray(R.array.EstateCategory)
for (i in 0..obje.resources.getStringArray(R.array.realEstateCategory).size -1 ){
categoryArraylist.add(Category[i])
}
}
Wtihin this method, I cant reach "resources". To solve this, I created and object from AppCombatActivity class. But it gives error like below at "var obje = AppCompatActivity()" line.
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference
How can I reach resources with this method? "this", or "context" doesn't works.
Pass in the itemView into the insertData method and call the resources the same way you're calling them in other places
insertData(itemView: View) {// along with your other parameters
itemView.resources.getStringArray(..)
}