从另一个 activity 启动一个 activity 会跳过很多 (96) 帧
Launching an activity from another activity skips a lot (96) frames
我有一个应用程序有两个活动 - LoginActivity (LA) 和 AppActivity (AA)。正如你所猜到的,LA 在登录成功后启动 AA。出于调试目的,我删除了所有登录逻辑,并用启动 AA 的简单按钮替换它。
AA 包含在 Fragment 上,它包含一个具有三个视图的 viewpager,其中一个视图使用 Kotlin 协程读取音乐文件并填充到 Recyclerview 中。其他两个视图做一些不同的事情,不涉及任何类型的文件 I/O 或 api 请求,简单静态 UI.
每当我启动该应用程序时,我都会看到三次跳帧警告
- 在洛杉矶点击按钮启动 AA(跳过 40 帧)
- AA 开始时(跳过 74 帧)
- 在 AA 完整加载包括子片段(跳过 38 帧)
我已经尝试 android studio profiler 来找出导致此问题的原因,但我没有这样做。
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()
}
编辑:我发现了跳帧的问题之一。语音合成
onCreate 中的引擎初始化导致问题。所以我把它
在一个线程中,但我仍然有跳帧问题
现在它不像以前那么高,但仍然很重要。还是三个跳帧的警告。
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()
}
}
}
}
我还注释掉了 viewPager,其他两个跳帧警告都消失了。现在,我不想删除viewpager,所以我还在调试,很快就会在这里更新。
我在几个应用程序中遇到了同样的问题,
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,
}
当我们启动一个activity时,activity将在oncreate完成并调用onstart后立即启动,所以我们必须让onCreate
顺利完成,这将使activity立即启动。
我有一个应用程序有两个活动 - LoginActivity (LA) 和 AppActivity (AA)。正如你所猜到的,LA 在登录成功后启动 AA。出于调试目的,我删除了所有登录逻辑,并用启动 AA 的简单按钮替换它。
AA 包含在 Fragment 上,它包含一个具有三个视图的 viewpager,其中一个视图使用 Kotlin 协程读取音乐文件并填充到 Recyclerview 中。其他两个视图做一些不同的事情,不涉及任何类型的文件 I/O 或 api 请求,简单静态 UI.
每当我启动该应用程序时,我都会看到三次跳帧警告
- 在洛杉矶点击按钮启动 AA(跳过 40 帧)
- AA 开始时(跳过 74 帧)
- 在 AA 完整加载包括子片段(跳过 38 帧)
我已经尝试 android studio profiler 来找出导致此问题的原因,但我没有这样做。
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()
}
编辑:我发现了跳帧的问题之一。语音合成 onCreate 中的引擎初始化导致问题。所以我把它 在一个线程中,但我仍然有跳帧问题 现在它不像以前那么高,但仍然很重要。还是三个跳帧的警告。
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()
}
}
}
}
我还注释掉了 viewPager,其他两个跳帧警告都消失了。现在,我不想删除viewpager,所以我还在调试,很快就会在这里更新。
我在几个应用程序中遇到了同样的问题,
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,
}
当我们启动一个activity时,activity将在oncreate完成并调用onstart后立即启动,所以我们必须让onCreate
顺利完成,这将使activity立即启动。