I am trying to build an app that uses the youtube API. I need to call the search API, whenever the user searches for something and then display the results in a new activity(SearchResultsActivity). However the scenario I get is that my app, rather than opening the SearchResultsActivity gets redirected to the MainActivity. The scenario is recorded, and can be better understood through this https://drive.google.com/file/d/1WESzXbRbjhmKCY1gfUq1d2gllIEsILCf/view?usp=sharing.
I want to know what is causing the SearchResultsActivity to be paused by itself and MainActivity being restarted instead. I tried logging the lifecycles to know what was happening and I found this:
Also Search box activity here means the SearchActivity:
package com.example.mytube.UI
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.KeyEvent
import android.view.View
import android.widget.EditText
import android.widget.ImageView
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.mytube.R
import com.example.mytube.adapters.SearchedHistoryAdapter
import com.example.mytube.db.SearchDatabase
import com.example.mytube.repository.VideosRepository
class SearchActivity : AppCompatActivity() {
lateinit var searchAdapter: SearchedHistoryAdapter
lateinit var viewModel: VideosViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_search)
val repository = VideosRepository(SearchDatabase.getSearchDatabase(this))
val viewModelFactory = VideosViewModelProviderFactory(repository)
viewModel = ViewModelProvider(this,viewModelFactory).get(VideosViewModel::class.java)
val recyclerView = findViewById<RecyclerView>(R.id.searched_terms)
searchAdapter = SearchedHistoryAdapter()
recyclerView.apply {
adapter = searchAdapter
layoutManager = LinearLayoutManager(this@SearchActivity)
}
val backButton = findViewById<ImageView>(R.id.ivGoback)
backButton.apply {
setOnClickListener {
finish()
}
}
val searchBar = findViewById<EditText>(R.id.search_box)
val searchBtn = findViewById<ImageView>(R.id.ivSearch)
searchBtn.setOnClickListener {
if (searchBar.text.toString().isNotEmpty()) {
viewModel.insertSearchItem(searchBar.text.toString())
val intent = Intent(applicationContext, SearchResultsActivity::class.java)
intent.putExtra("searchQuery", searchBar.text)
startActivity(intent)
}
}
searchBar.setOnKeyListener(View.OnKeyListener{v, keyCode, event ->
if (event.action == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_ENTER) {
if (searchBar.text.toString().isNotEmpty()) {
viewModel.insertSearchItem(searchBar.text.toString())
}
return@OnKeyListener true
}
return@OnKeyListener false
})
viewModel.getSearchHistory().observe(this, Observer { searchItems ->
searchAdapter.differ.submitList(searchItems)
})
}
override fun onPause() {
super.onPause()
Log.d("searched", "Search box activity paused")
}
override fun onStop() {
super.onStop()
Log.d("searched", "Search box activity stopped")
}
override fun onDestroy() {
super.onDestroy()
Log.d("searched", "Search box activity destroyed")
}
}
The SearchResultsActivity:
package com.example.mytube.UI
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.AbsListView
import android.widget.ProgressBar
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.mytube.R
import com.example.mytube.adapters.VideosAdapter
import com.example.mytube.db.SearchDatabase
import com.example.mytube.repository.VideosRepository
import com.example.mytube.util.Resource
class SearchResultsActivity : AppCompatActivity() {
lateinit var viewModel: VideosViewModel
lateinit var videosAdapter: VideosAdapter
var searchQuery = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_search_results)
searchQuery = intent.getStringExtra("searchQuery").toString()
val repository = VideosRepository(SearchDatabase.getSearchDatabase(this))
val viewModelFactory = VideosViewModelProviderFactory(repository)
viewModel = ViewModelProvider(this,viewModelFactory).get(VideosViewModel::class.java)
videosAdapter = VideosAdapter(viewModel)
val recyclerView = findViewById<RecyclerView>(R.id.videos)
recyclerView.apply {
layoutManager = LinearLayoutManager(this@SearchResultsActivity)
adapter = videosAdapter
addOnScrollListener(this@SearchResultsActivity.scrollListener)
}
val progressBar = findViewById<ProgressBar>(R.id.paginationProgressBar)
viewModel.getSearchResults(searchQuery)
viewModel.searchResults.observe(this, Observer { resource ->
when(resource) {
is Resource.Success -> {
hideProgressBar(progressBar)
resource.data?.let { videoResponse ->
if (viewModel.nextSearchPageId != videoResponse.nextPageToken) {
viewModel.nextSearchPageId = videoResponse.nextPageToken
viewModel.searchedVideos.addAll(videoResponse.items)
// videoResponse.items.forEach { viewModel.getChannel(it.snippet.channelId) }
Log.d("Channels", viewModel.channels.toString())
videosAdapter.differ.submitList(viewModel.searchedVideos.toList())
}
else {
Log.d("Videos", "next token dekh ${viewModel.nextPageId}")
videosAdapter.differ.submitList(viewModel.searchedVideos.toList())
}
}
}
is Resource.Error -> {
hideProgressBar(progressBar)
Log.e("Videos", resource.message.toString())
}
is Resource.Loading -> {
showProgressBar(progressBar)
}
}
})
viewModel.channelResponse.observe(this, Observer { resource ->
when (resource) {
is Resource.Success -> {
resource.data?.let { channels ->
viewModel.channels.set(channels.items[0].id, channels.items[0])
// videosAdapter.differ.submitList(viewModel.videos.toList())
}
}
is Resource.Error -> {
Log.e("Channels", resource.message.toString())
}
is Resource.Loading -> {
Log.d("Channels", "Waiting")
}
}
})
}
private fun hideProgressBar(bar: ProgressBar) {
bar.visibility = View.INVISIBLE
isLoading = false
}
private fun showProgressBar(bar: ProgressBar){
bar.visibility = View.VISIBLE
isLoading = true
}
var isScrolling = false
var isLoading = false
val scrollListener = object: RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
isScrolling = true
}
}
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
val manager = recyclerView.layoutManager as LinearLayoutManager
val currentItems = manager.childCount
val totaltItems = manager.itemCount
val scrolledItems = manager.findFirstVisibleItemPosition()
if (isScrolling && totaltItems == currentItems + scrolledItems && !isLoading && viewModel.searchedVideos.size <= 1_000_000) {
viewModel.getNextSearchResults(searchQuery)
isScrolling = false
} else {
videosAdapter.differ.submitList(viewModel.searchedVideos.toList())
recyclerView.setPadding(0, 0, 0, 0)
Log.d("Videos", viewModel.searchedVideos.size.toString())
}
}
}
override fun onPause() {
super.onPause()
Log.d("searched", "Search Results Activity paused")
}
override fun onStop() {
super.onStop()
Log.d("searched", "Search Results Activity stopped")
}
override fun onDestroy() {
super.onDestroy()
Log.d("searched", "Search Results Activity destroyed")
}
}
The logcat shows the following error: 2021-09-28 12:51:06.200 1207-2988/? W/ActivityTaskManager: Force finishing activity com.example.mytube/.UI.SearchResultsActivity
For recreating the error, here is the gitHub repo to the app: https://github.com/AkhilrajNambiar/MyTube-1
Thanks in advance!