No adapter attached; skipping layout kotlin - android-studio

It loads fine at startup but when I navigate to other fragments and go back to Home Fragment, the recycler view doesn't load anymore. It loads fine with other fragments when I navigate back to it, only the recycler view of Home Fragment doesn't show. There is no error showing in the logcat. Only this W/RecyclerView: No adapter attached; skipping layout. Anyone can help me? I don't know what's really wrong here. Thank you in advance guys.
Here is my code of HOME FRAGMENT
class HomeFragment : Fragment() {
private lateinit var homeViewModel: HomeViewModel
var recyclerView:RecyclerView?=null
lateinit var swipeUpToRefresh:SwipeRefreshLayout
private var viewPager:LoopingViewPager?=null
private var layoutAnimationController:LayoutAnimationController?=null
private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
homeViewModel =
ViewModelProvider(this).get(HomeViewModel::class.java)
_binding = FragmentHomeBinding.inflate(inflater, container, false)
val root: View = binding.root
val key = requireArguments().getString("restaurant")
initView(root)
refreshPage()
//bind data
homeViewModel.getPopularList(key!!).observe(viewLifecycleOwner, {
val listData = it
val adapter = MyPopularCategoriesAdapter(requireContext(), listData)
recyclerView!!.adapter = adapter
recyclerView!!.layoutAnimation = layoutAnimationController
})
homeViewModel.getBestDealList(key).observe(viewLifecycleOwner, {
val adapter = MyBestDealsAdapter(requireContext(), it, false)
viewPager!!.adapter = adapter
})
return root
}
private fun refreshPage() {
val key = requireArguments().getString("restaurant")
swipeUpToRefresh.setOnRefreshListener {
//bind data
homeViewModel.getPopularList(key!!).observe(viewLifecycleOwner, {
val listData = it
val adapter = MyPopularCategoriesAdapter(requireContext(), listData)
recyclerView!!.adapter = adapter
recyclerView!!.layoutAnimation = layoutAnimationController
})
homeViewModel.getBestDealList(key).observe(viewLifecycleOwner, {
val adapter = MyBestDealsAdapter(requireContext(), it, false)
viewPager!!.adapter = adapter
})
swipeUpToRefresh.isRefreshing = false
}
}
private fun initView(root:View) {
swipeUpToRefresh = root.findViewById(R.id.refresh) as SwipeRefreshLayout
layoutAnimationController = AnimationUtils.loadLayoutAnimation(context, R.anim.layout_item_from_left)
viewPager = root.findViewById(R.id.viewpager) as LoopingViewPager
recyclerView = root.findViewById(R.id.recycler_popular) as RecyclerView
recyclerView!!.setHasFixedSize(true)
recyclerView!!.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
}
override fun onResume() {
super.onResume()
viewPager!!.resumeAutoScroll()
}
override fun onPause() {
viewPager!!.pauseAutoScroll()
super.onPause()
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}}

I added this line of code to my HomeActivity in R.id.nav_home
val bundle = Bundle()
bundle.putString("restaurant",Common.currentRestaurant!!.uid)
navController.navigate(R.id.nav_home,bundle)
here Is my navView
navView!!.setNavigationItemSelectedListener { p0 ->
p0.isChecked = true
drawer!!.closeDrawers()
if (p0.itemId == R.id.nav_sign_out) {
signOut()
} else if (p0.itemId == R.id.nav_restaurant) {
if (menuItemClick != p0.itemId)
navController.popBackStack()
navController.navigate(R.id.nav_restaurant)
} else if (p0.itemId == R.id.nav_home) {
if (menuItemClick != p0.itemId) {
EventBus.getDefault().postSticky(MenuInflateEvent(true))
navController.popBackStack()
val bundle = Bundle()
bundle.putString("restaurant",Common.currentRestaurant!!.uid)
navController.navigate(R.id.nav_home,bundle)
}
} else if (p0.itemId == R.id.nav_cart) {
if (menuItemClick != p0.itemId) {
EventBus.getDefault().postSticky(MenuInflateEvent(true))
navController.popBackStack()
navController.navigate(R.id.nav_cart)
}
} else if (p0.itemId == R.id.nav_menu) {
if (menuItemClick != p0.itemId) {
EventBus.getDefault().postSticky(MenuInflateEvent(true))
navController.popBackStack()
navController.navigate(R.id.nav_menu)
}
} else if (p0.itemId == R.id.nav_view_order) {
if (menuItemClick != p0.itemId) {
EventBus.getDefault().postSticky(MenuInflateEvent(true))
navController.popBackStack()
navController.navigate(R.id.nav_view_order)
}
} else if (p0.itemId == R.id.nav_update_info) {
showUpdateDialog()
}
menuItemClick = p0.itemId
true
}

Try doing this
private fun initView(root:View) {
swipeUpToRefresh = root.findViewById(R.id.refresh) as SwipeRefreshLayout
layoutAnimationController = AnimationUtils.loadLayoutAnimation(context, R.anim.layout_item_from_left)
viewPager = root.findViewById(R.id.viewpager) as LoopingViewPager
recyclerView = root.findViewById(R.id.recycler_popular) as RecyclerView
//Here is where you need to initialize an adapter to the recyclerView
recylerView!!.adapter = MyPopularCategoriesAdapter(requireContext(), listData) //I'm not sure what is the second argument of your adapter. Feel free to change it as you like.
recyclerView!!.setHasFixedSize(true)
recyclerView!!.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
}

Related

Load image from firestore collection into LazyColumn in jetpack compose

My app has a navigation bar and in one navBarItem I have two tabs, I want to read images and their caption I have stored in my firebase firestore collection into a LazyColumn in one of the tabs.
Here is how my DataException and GalleryRepo class looks like
data class DataOrException<T, E : Exception> (
var data: T? = null,
var e: E? = null
)
#Singleton
class GalleryRepo #Inject constructor(
private val queryImageData: Query
) {
fun getImagesFromFirestore(): DataOrException<List<PQImageGallery>, Exception> {
val dataOrException = DataOrException<List<PQImageGallery>, Exception>()
try {
dataOrException.data = queryImageData.get()
.result.map { document -> document.toObject(PQImageGallery::class.java) }
} catch (e: FirebaseFirestoreException) {
dataOrException.e = e
}
return dataOrException
}
}
My data class
data class PQImageGallery (
var imageUrl: String? =null,
var caption: String? = null
)
ViewModels...
#HiltViewModel
class PQViewModel #Inject constructor(
private val repository: GalleryRepo
): ViewModel() {
var loading = mutableStateOf(false)
val data: MutableState<DataOrException<List<PQImageGallery>, Exception>> = mutableStateOf(
DataOrException(
listOf(),
Exception("")
)
)
init {
getGalleryCollection()
}
private fun getGalleryCollection() {
viewModelScope.launch {
loading.value = true
data.value = repository.getImagesFromFirestore()
loading.value = false
}
}
}
#Module
#InstallIn(SingletonComponent::class)
object RemoteImageModel {
#Provides
#Singleton
fun loadImagesInCollection() = FirebaseFirestore.getInstance()
.collection(IMAGE_COLLECTION)
}
My GalleryCollection composable file
#Composable
fun GalleryCollection(dataOrException: DataOrException<List<PQImageGallery>, Exception>) {
val images = dataOrException.data
images?.let {
LazyColumn {
items(items = images) { product ->
GalleryCard(pqImageGallery = product)
}
}
}
val e = dataOrException.e
e?.let {
Text(
text = e.message!!,
modifier = Modifier.padding(16.dp)
)
}
}
#Composable
fun GalleryCard(
pqImageGallery: PQImageGallery,
) {
Card(...) {
Box(modifier = Modifier
.fillMaxSize()
) {
pqImageGallery.imageUrl?.let { imageUrl ->
CoilImage(
data = imageUrl,
....
)
}
pqImageGallery.caption?.let { caption ->
Text(
text = caption,
...
)
}
}
}
}
My navBarItem that contains the two tabs called Home
class Home : ComponentActivity() {
private val viewModel: PQViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
HomeScreen(viewModel)
}
}
}
#Composable
fun HomeScreen(
viewModel: PQViewModel
) {
val dataOrException = viewModel.data.value
val navController = rememberNavController()
val currentBackStack by navController.currentBackStackEntryAsState()
val currentDestination = currentBackStack?.destination
val currentScreen =
HomeTabRowScreens.find { it.route == currentDestination?.route } ?: GalleryView
Scaffold(
topBar = {
HomeScreenTabRow(
allScreens = HomeTabRowScreens,
onTabSelected = { newScreen ->
navController
.navigateSingleTopTo(newScreen.route)
},
currentScreen = currentScreen,
)
}
) { innerPadding ->
NavHost(
navController = navController,
startDestination = GalleryView.route,
modifier = Modifier.padding(innerPadding)
) {
composable(route = GalleryView.route) {
// GalleryTabScreen()
GalleryCollection(dataOrException = dataOrException)
}
composable(route = VirtualTourView.route) {
VirtualTourScreen()
}
}
}
}
fun NavHostController.navigateSingleTopTo(route: String) =
this.navigate(route) {
popUpTo(
this#navigateSingleTopTo.graph.findStartDestination().id
) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
Finally calling the Home class in my main screen(MainActivity)
NavHost(
..
) {
composable(NAV_HOME) {
Home()
}
composable(..) { ...}
}
The issue is when I run the app the tabs in the Home navBar doesn't show at all talk of loading the images from the firestore collection.
Also, is there another way to instantiate a viewModel without having to create a class that extends ComponentActiviy?
If there's another way to achieve this kindly share.

Kotlin Edit Text as Integer

I want to make an app where you have to guess two numbers that eaquals a random number. But my app crash at the start because of java.lang.NumberFormatException: For input string: ""
val intNumber1 = etNumber1.text.toString().toInt() is the line that causes the crash. But I dont know what to do.
Here is my main activity:
//Buttons und Text initialisieren
private lateinit var btnCheck: Button
private lateinit var tvRndNumber: TextView
private lateinit var etNumber1: EditText
private lateinit var etNumber2: EditText
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//Buttons und Text verknüpfen
btnCheck = findViewById(R.id.checkButton)
tvRndNumber = findViewById(R.id.randomNumber)
etNumber1 = findViewById(R.id.inputNumber1)
etNumber2 = findViewById(R.id.inputNumber2)
val intNumber1 = etNumber1.text.toString().toInt()
val intNumber2 = etNumber2.text.toString().toInt()
fun getRandomNumber(): Int {
return Random.nextInt(0,100)
}
var intRdnNumber = getRandomNumber()
tvRndNumber.text = intRdnNumber.toString()
fun checkNumbers(num1: Int, num2: Int){
if (num1 + num2 == intRdnNumber) {
tvRndNumber.text = "Richtig"
}
else {
Toast.makeText(this,"Probier es nochmal", Toast.LENGTH_LONG).show()
}
}
btnCheck.setOnClickListener {
checkNumbers(intNumber1, intNumber2)
}
Try like the following
//....
val intNumber1 = etNumber1.text.toString()
val intNumber2 = etNumber2.text.toString()
//.....
btnCheck.setOnClickListener {
if(intNumber1.isNotEmpty && intNumber2.isNotEmpty{
checkNumbers(intNumber1.toInt(), intNumber2.toInt())
}else{
// input filed is empty
// show message or do nothing
}
}
val intNumber1 = if(etNumber1.text.isNotEmpty()) {
etNumber1.text.toString().toInt()
} else {
0
}
val intNumber2 = if(etNumber2.text.isNotEmpty()) {
etNumber2.text.toString().toInt()
} else {
0
}

How can an App write and read file in Documents folder?

I wrote an App, in Kotlin with Android Studio that write some strings to a file.
All work, I can write and read inside the App, but I can't see the file looking in Documents folder.
How can I use the folder Documents as a storage space?
Thank you
These are the function I use:
fun saveTextFile(view: View, nomeFile: String, testo: String, contesto: Context){
var fileStream: FileOutputStream
try {
fileStream = contesto.openFileOutput(nomeFile, MODE_APPEND) // OK esegue append
fileStream.write(testo.toByteArray())
fileStream.close()
}catch (e: Exception){
e.printStackTrace()
}
}
fun readTextFile(view: View, nomeFile: String, contesto: Context): String{
var fileInputStream: FileInputStream? = null
fileInputStream = contesto.openFileInput(nomeFile)
var inputStreamReader: InputStreamReader = InputStreamReader(fileInputStream)
val bufferedReader: BufferedReader = BufferedReader(inputStreamReader)
val stringBuilder: StringBuilder = StringBuilder()
var text: String? = null
while ({ text = bufferedReader.readLine(); text }() != null) {
stringBuilder.append(text)
}
inputStreamReader.close();
return(stringBuilder.toString())
}
Thank you, Livio
For writing in Documents folder of your device , you just need to make use of MediaStore for the same. You can take input for this function anything that you want like String , bitmap , PdfDocument and other's too .
For Your UseCase you can do the following ,
Global Variable :
private var imageUri: Uri? = null
override suspend fun saveDocument(context : Context, text : String) {
withContext(Dispatchers.IO) {
try {
val collection =
MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val dirDest = File(
Environment.DIRECTORY_DOCUMENTS,
context.getString(R.string.app_name)
)
val date = System.currentTimeMillis()
val fileName = "$date.txt"
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
put(MediaStore.MediaColumns.RELATIVE_PATH,
"$dirDest${File.separator}")
put(MediaStore.Files.FileColumns.IS_PENDING, 1)
}
}
val imageUri = context.contentResolver.insert(collection, contentValues)
withContext(Dispatchers.IO) {
imageUri?.let { uri ->
context.contentResolver.openOutputStream(uri, "w").use { out -> out?.write(text.toByteArray())
}
contentValues.clear()
contentValues.put(MediaStore.Files.FileColumns.IS_PENDING, 0)
context.contentResolver.update(uri, contentValues, null, null)
}
}
} catch (e: FileNotFoundException) {
null
}
}
}
For Updating the already existing file , do the following . After creating file for the first time I have saved the imageUri in a global variable (If you want to store it permanently / or for a while you can use Jetpack Datastore / Shared Preference to save the same ):
suspend fun updateData(context: Context,text : String){
withContext(Dispatchers.IO) {
try {
val collection =
MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val dirDest = File(
Environment.DIRECTORY_DOCUMENTS,
context.getString(R.string.app_name)
)
val fileName = "test.txt"
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
put(
MediaStore.MediaColumns.RELATIVE_PATH,
"$dirDest${File.separator}"
)
put(MediaStore.Files.FileColumns.IS_PENDING, 1)
}
withContext(Dispatchers.IO) {
imageUri?.let { uri ->
context.contentResolver.openOutputStream(uri, "wa").use { out ->
out?.write(text.toByteArray())
}
contentValues.clear()
contentValues.put(MediaStore.Files.FileColumns.IS_PENDING, 0)
context.contentResolver.update(uri, contentValues, null, null)
}
}
} catch (e: FileNotFoundException) {
null
}
}
}
For Reading the File , Do the following :
suspend fun read(context: Context, source: Uri): String = withContext(Dispatchers.IO) {
val resolver: ContentResolver = context.contentResolver
resolver.openInputStream(source)?.use { stream -> stream.readText() }
?: throw IllegalStateException("could not open $source")
}
private fun InputStream.readText(charset: Charset = Charsets.UTF_8): String =
readBytes().toString(charset)
This is how the final code looks like :
class MainActivity : AppCompatActivity() {
private lateinit var btn: Button
private var imageUri: Uri? = null
private lateinit var btn2: Button
private lateinit var btn3 : Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btn = findViewById(R.id.btnAdd)
btn2 = findViewById(R.id.getText)
btn3 = findViewById(R.id.updateText)
btn.setOnClickListener {
lifecycleScope.launch {
saveDocument(applicationContext, "Original ")
}
}
btn3.setOnClickListener {
lifecycleScope.launch {
updateData(applicationContext,"Appended")
}
}
btn2.setOnClickListener {
lifecycleScope.launch {
imageUri?.let { it1 ->
val data = read(applicationContext, it1)
Toast.makeText(applicationContext, "The data is $data ", Toast.LENGTH_LONG)
.show()
}
}
}
}
suspend fun saveDocument(context: Context, text: String) {
withContext(Dispatchers.IO) {
try {
val collection =
MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val dirDest = File(
Environment.DIRECTORY_DOCUMENTS,
context.getString(R.string.app_name)
)
val date = System.currentTimeMillis()
val fileName = "test.txt"
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
put(
MediaStore.MediaColumns.RELATIVE_PATH,
"$dirDest${File.separator}"
)
put(MediaStore.Files.FileColumns.IS_PENDING, 1)
}
imageUri = context.contentResolver.insert(collection, contentValues)
withContext(Dispatchers.IO) {
imageUri?.let { uri ->
context.contentResolver.openOutputStream(uri, "w").use { out ->
out?.write(text.toByteArray())
}
contentValues.clear()
contentValues.put(MediaStore.Files.FileColumns.IS_PENDING, 0)
context.contentResolver.update(uri, contentValues, null, null)
}
}
} catch (e: FileNotFoundException) {
null
}
}
}
suspend fun updateData(context: Context, text: String) {
withContext(Dispatchers.IO) {
try {
val collection =
MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val dirDest = File(
Environment.DIRECTORY_DOCUMENTS,
context.getString(R.string.app_name)
)
val fileName = "test.txt"
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
put(
MediaStore.MediaColumns.RELATIVE_PATH,
"$dirDest${File.separator}"
)
put(MediaStore.Files.FileColumns.IS_PENDING, 1)
}
withContext(Dispatchers.IO) {
imageUri?.let { uri ->
context.contentResolver.openOutputStream(uri, "wa").use { out ->
out?.write(text.toByteArray())
}
contentValues.clear()
contentValues.put(MediaStore.Files.FileColumns.IS_PENDING, 0)
context.contentResolver.update(uri, contentValues, null, null)
}
}
} catch (e: FileNotFoundException) {
null
}
}
}
suspend fun read(context: Context, source: Uri): String = withContext(Dispatchers.IO) {
val resolver: ContentResolver = context.contentResolver
resolver.openInputStream(source)?.use { stream -> stream.readText() }
?: throw IllegalStateException("could not open $source")
}
private fun InputStream.readText(charset: Charset = Charsets.UTF_8): String =
readBytes().toString(charset)
I have three buttons . With the first I create a file , then the uri gets stored in the global variable . Then onClick of second button I add to the already existing file and then read the file using the third button using the same imageUri stored in the global variable
This is the demo for the same . Check when the buttons are being pressed and the output in the form of Toast at the bottom .

The step counter sensor is not working for my app. Could you please tell me what the problem is? I have been trying to debug this for days now

TYPE_STEP_COUNTER is not working with this code. Could anyone please tell me what is wrong.
My min sdk is 19 and target sdk is 30. I have also tried using TYPE_STEP_COUNTER instead number of 19 but it still does not work. Please help!!
I have been trying to debug this for hours now. I am using pixel 3 to test this and I see that the required sensor is here but for some reason this is not working.
class MainActivity : AppCompatActivity(), SensorEventListener, View.OnClickListener {
var running = false
private var sensorManager: SensorManager? = null
lateinit var sharebutton: Button
lateinit var goalnum: Button
lateinit var et: EditText
lateinit var tv: EditText
lateinit var progress: ProgressBar
lateinit var step2: EditText
var steps=0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.mainlayout)
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
sharebutton = findViewById(R.id.share) as Button
tv = findViewById(R.id.tv) as EditText
sharebutton.setOnClickListener(this)
goalnum = findViewById(R.id.goalnum) as Button
goalnum.setOnClickListener(this)
val circularProgressBar = findViewById<CircularProgressBar>(R.id.progressBar)
val toolbar = findViewById(R.id.tbar) as Toolbar?
setSupportActionBar(toolbar)
getSupportActionBar()?.setTitle("");
//manualInc()
}
override fun onResume() {
//manualInc()
Toast.makeText(this, "I am in", Toast.LENGTH_SHORT).show()
super.onResume()
running = true;
var StepSensor = sensorManager?.getDefaultSensor(19)
if (StepSensor == null) {
Toast.makeText(this, "No Step Counter Sensor !", Toast.LENGTH_SHORT).show()
} else {
sensorManager?.registerListener(this, StepSensor, SensorManager.SENSOR_DELAY_UI)
}
}
fun manualInc(){
steps =100
var step2 = tv.getText().toString().toInt()
var steps3 = (step2 - steps)
tv_steps.setText("" + steps.toInt())
if (steps3 > 0) {
tv_steps2.setText("" + (steps3).toInt());
} else {
tv_steps2.setText("Goal Reached!");
}
val currentsteps = step2 - steps.toInt()
progressBar.apply{
setProgressWithAnimation(currentsteps.toFloat())
}
if(steps> step2) {
Toast.makeText(this, "GOAL REACHED!!! Amazing job!", Toast.LENGTH_LONG).show()
}
}
override fun onPause() {
super.onPause()
running = true;
var StepSensor = sensorManager?.getDefaultSensor(19)
if (StepSensor == null) {
Toast.makeText(this, "No Step Counter Sensor !", Toast.LENGTH_SHORT).show()
} else {
sensorManager?.registerListener(this, StepSensor, SensorManager.SENSOR_DELAY_UI)
}
}
override fun onClick(view: View?) {
when (view?.id) {
R.id.goalnum -> {
var goalcount = tv.getText().toString().toDouble()
userinput.setText("" + goalcount.toInt())
Toast.makeText(this, "Great goal!", Toast.LENGTH_LONG).show()
}
R.id.share -> {
val sendIntent: Intent = Intent().apply {
var goalcount = tv.getText().toString().toInt()
action = Intent.ACTION_SEND
putExtra(
Intent.EXTRA_TEXT,
"I am on my way to reaching my goal of " + goalcount + " daily steps! Join me on Step Counter and Tracker"
)
type = "text/plain"
}
startActivity(Intent.createChooser(sendIntent, null))
}
}
}
override fun onAccuracyChanged(p0: Sensor?, p1: Int) {
}
override fun onSensorChanged(event: SensorEvent) {
Toast.makeText(this, "I am i", Toast.LENGTH_LONG).show()
if (running) {
val steps = (event.values[0])
var step2 = tv.getText().toString().toInt()
var steps3 = (step2 - steps)
tv_steps.setText("" + steps.toInt())
if (steps3 > 0) {
tv_steps2.setText("" + (steps3).toInt());
} else {
tv_steps2.setText("Goal Reached!");
}
val currentsteps = step2 - steps.toInt()
progressBar.apply{
setProgressWithAnimation(currentsteps.toFloat())
}
if(steps> step2) {
Toast.makeText(this, "GOAL REACHED!!! Amazing job!", Toast.LENGTH_LONG).show()
}}}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater: MenuInflater = menuInflater
inflater.inflate(R.menu.menu, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
// Handle presses on the action bar menu items
when (item.itemId) {
R.id.action_one -> {
val intent = Intent(this, MainActivity::class.java)
finishAffinity();
startActivity(intent)
}
R.id.action_two -> {
val intent = Intent(this, ExerciseHistory::class.java)
startActivity(intent)
}
R.id.action_three -> {
val intent = Intent(this, ViewListContents::class.java)
startActivity(intent)
}
R.id.action_four -> {
val intent = Intent(this, StepHistory::class.java)
startActivity(intent)
}
R.id.action_five -> {
val intent = Intent(this, Help::class.java)
startActivity(intent)
Toast.makeText(
this,
"Please leave feedback!",
Toast.LENGTH_SHORT
).show()
}
}
return super.onOptionsItemSelected(item)
}
}

how to fix conversion error when converting from java to kotlin

I am a student, new to kotlin, so I am converting java codes to kotlin to learn and see how it works, but I didnt understand what the error says.
private val _songs = ArrayList<SongInfo>()
internal lateinit var recyclerView: RecyclerView
internal lateinit var seekBar: SeekBar
internal lateinit var songAdapter: SongAdapter
internal var mediaPlayer: MediaPlayer? = null
private val myHandler = Handler()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recyclerView = findViewById(R.id.recyclerView) as RecyclerView
seekBar = findViewById(R.id.seekBar) as SeekBar
songAdapter = SongAdapter(this, _songs)
recyclerView.adapter = songAdapter
val linearLayoutManager = LinearLayoutManager(this)
val dividerItemDecoration = DividerItemDecoration(recyclerView.context,
linearLayoutManager.orientation)
recyclerView.layoutManager = linearLayoutManager
recyclerView.addItemDecoration(dividerItemDecoration)
songAdapter.setOnItemClickListener { b, view, obj, position ->
if (b.text == "Stop") {
mediaPlayer!!.stop()
mediaPlayer!!.reset()
mediaPlayer!!.release()
mediaPlayer = null
b.text = "Play"
} else {
val runnable = Runnable {
try {
mediaPlayer = MediaPlayer()
mediaPlayer!!.setDataSource(obj.songUrl)
mediaPlayer!!.prepareAsync()
mediaPlayer!!.setOnPreparedListener { mp ->
mp.start()
seekBar.progress = 0
seekBar.max = mediaPlayer!!.duration
Log.d("Prog", "run: " + mediaPlayer!!.duration)
}
b.text = "Stop"
} catch (e: Exception) {
}
}
myHandler.postDelayed(runnable, 100)
}
}
checkUserPermission()
val t = runThread()
t.start()
}
inner class runThread : Thread() {
override fun run() {
while (true) {
try {
Thread.sleep(1000)
} catch (e: InterruptedException) {
e.printStackTrace()
}
Log.d("Runwa", "run: " + 1)
if (mediaPlayer != null) {
seekBar.post { seekBar.progress = mediaPlayer!!.currentPosition }
Log.d("Runwa", "run: " + mediaPlayer!!.currentPosition)
}
}
}
}
private fun checkUserPermission() {
if (Build.VERSION.SDK_INT >= 23) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 123)
return
}
}
loadSongs()
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
when (requestCode) {
123 -> if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
loadSongs()
} else {
Toast.makeText(this, "Permission Denied", Toast.LENGTH_SHORT).show()
checkUserPermission()
}
else -> super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
}
private fun loadSongs() {
val uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
val selection = MediaStore.Audio.Media.IS_MUSIC + "!=0"
val cursor = contentResolver.query(uri, null, selection, null, null)
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
val name = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME))
val artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST))
val url = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA))
val s = SongInfo(name, artist, url)
_songs.add(s)
} while (cursor.moveToNext())
}
cursor.close()
songAdapter = SongAdapter(this#MainActivity, _songs)
}
}
}
This is the error:
"Error:(46, 44) Type mismatch: inferred type is (???, ???, ???, ???)
-> Any but SongAdapter.OnItemClickListener was expected Error:(46, 46) Cannot infer a type for this parameter. Please specify it explicitly."
Batch conversion to Kotlin is not the best way to learn the language. I suggest you to re-implement your Android component in Kotlin manually, to get the feeling of language.
The error you see says: "I can not understand how this lambda with 4 parameters can be an instance of SongAdapter.OnItemClickListener, please help". You can try anonymous class in this place.

Resources