Reputation: 1016
I have an app which had two activities - LoginActivity (LA) and AppActivity (AA). As you have guessed, LA launches AA upon successful log. For the debugging purpose, I removed all the login logic and replaced it with the simple button to launch AA.
AA containes on Fragment which contain a viewpager with three views in which one of the view reads music file using Kotlin co-routines and populate into a Recyclerview. And other two views do something different which doesn't involve any kind of file I/O or api request, simple static UI.
Whenever I launch the app, I see skipping frames warning three time
I have tried android studio profiler to find out which one is causing this but I failed to do so.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
/*Permissions*/
val permissions = listOf(
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.BLUETOOTH,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO
)
validatePermission(permissions)
}
fun startActivity(view: View) {
val intent = Intent(this, AppActivity::class.java)
startActivity(intent)
finish()
}
private fun validatePermission(permissions: List<String>) {
Dexter.withContext(this)
.withPermissions(permissions)
.withListener(
object : MultiplePermissionsListener {
override fun onPermissionsChecked(p0: MultiplePermissionsReport?) {
}
override fun onPermissionRationaleShouldBeShown(
p0: MutableList<PermissionRequest>?,
p1: PermissionToken?
) {
AlertDialog.Builder(this@LoginActivity)
.setTitle(R.string.storage_permission_rationale_title)
.setMessage(R.string.storage_permission_rationale_message)
.setNegativeButton(
android.R.string.cancel,
DialogInterface.OnClickListener { dialogInterface, i ->
dialogInterface.dismiss()
p1?.cancelPermissionRequest()
})
.setPositiveButton(
android.R.string.ok,
DialogInterface.OnClickListener { dialogInterface, _ ->
dialogInterface.dismiss()
p1?.continuePermissionRequest()
})
.show()
}
}
).check()
}
Edit: I have found one of the problems with skipping frame. TTS engine initialization inside onCreate causing problems. So I put it inside a thread but still I have skipping frame problem though right now it is not as high as before but still significant. Still three warnings for skipping frames.
class AppActivity : AppCompatActivity(), TextToSpeech.OnInitListener{
private lateinit var appBarConfiguration: AppBarConfiguration
private var engine: TextToSpeech? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_app)
val toolbar: Toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
appBarConfiguration = AppBarConfiguration(setOf(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow), drawerLayout)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
/*---Text to speech------*/
}
override fun onStart() {
super.onStart()
Thread(Runnable {
engine = TextToSpeech(this, this)
}).start()
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.main, menu)
return true
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment)
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
override fun onResume() {
super.onResume()
realTimeData()
}
/*---Test Code-----------*/
private var mHandler: Handler = Handler(Looper.myLooper()!!)
private lateinit var mTimer2:Runnable
private fun realTimeData(){
mTimer2 = object : Runnable {
override fun run() {
mHandler.postDelayed(this, 200)
}
}
mHandler.postDelayed(mTimer2, 200)
}
var mRand: Random = Random()
private fun getRandom(): Double {
return mRand.nextDouble() * 100
}
private fun playMessage(msg: String) {
engine!!.speak(msg, TextToSpeech.QUEUE_FLUSH, null, null)
}
override fun onDestroy() {
super.onDestroy()
if (engine != null) {
engine!!.stop()
engine!!.shutdown()
Log.d("TTS", "TTS Destroyed")
}
}
override fun onInit(status: Int) {
if (status == TextToSpeech.SUCCESS) {
val results = engine!!.setLanguage(Locale.US)
if (results == TextToSpeech.LANG_MISSING_DATA
|| results == TextToSpeech.LANG_NOT_SUPPORTED) {
Toast.makeText(this, "Not supported", Toast.LENGTH_LONG).show()
}
}
}
}
I have also commented out viewPager and other two skip frames warnings are gone. Now, I don't want to remove viewpager so I am still debugging and will update here soon.
Upvotes: 1
Views: 245
Reputation: 2056
In few apps I faced the same issue,
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_app)
val toolbar: Toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
appBarConfiguration = AppBarConfiguration(setOf(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow), drawerLayout)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
// Oncreate is the place for the initialization of things but if their initialization is CPU intensive then delaying them a bit will make things hassle-free.
Handler(Looper.getMainLooper()).postDelayed({
engine = TextToSpeech(this, this)
observers()//perform other intensive task after a delay,e.g. loading a url on webview.
},200)//delayed by 200ms,
}
When we start an activity the activity will be launched as soon as the oncreate finishes and onstart called, So we must let the onCreate
finish smoothly, Which will let the activity be launched immediately.
Upvotes: 2