【问题标题】:Launching an activity from another activity skips a lot (96) frames从另一个活动启动一个活动会跳过很多 (96) 帧
【发布时间】:2021-05-05 23:05:42
【问题描述】:

我有一个应用程序,它有两个活动 - LoginActivity (LA) 和 AppActivity (AA)。如您所料,LA 在成功登录后启动 AA。出于调试目的,我删除了所有登录逻辑,并用简单的按钮替换它以启动 AA。

AA 包含在 Fragment 上,其中包含一个具有三个视图的 viewpager,其中一个视图使用 Kotlin 协同程序读取音乐文件并填充到 Recyclerview 中。其他两个视图做一些不同的事情,不涉及任何类型的文件 I/O 或 api 请求,简单的静态 UI。

每当我启动应用程序时,我都会看到三次跳帧警告

  1. 在 LA 中单击按钮以启动 AA(跳过 40 帧)
  2. AA 开始时(跳过 74 帧)
  3. 在 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()
        }   


编辑:我发现了跳帧的问题之一。 TTS 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,所以我仍在调试中,很快就会在这里更新。

【问题讨论】:

  • 可以加AppActivity的代码
  • 我发现了三个跳帧警告之一。我正在初始化 TTS 引擎 - 在 AppAcitvity 中的 onCreate 中的 engine = TextToSpeech(this, this) 导致 84 帧跳过,所以我注释掉了,现在我只收到两个跳过帧的警告,而不是三个。
  • 那么,现在你不需要那个了吗?
  • 不,我需要它,所以我将它放在一个线程中。现在我正在尝试找出其他两个跳帧警告。
  • 如果能加代码,可以帮到你

标签: android kotlin android-activity fragment


【解决方案1】:

在几个应用程序中我遇到了同样的问题,

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时,一旦oncreate完成并调用了onstart,activity就会启动,所以我们必须让onCreate顺利完成,这样才能让activity立即启动。

【讨论】:

  • 我猜你的延迟初始化方法有效。谢谢你。我以为我写了一些愚蠢的代码。再次感谢你。我可以在我们的聊天中再问几个问题吗?
  • 我在我们的聊天中添加了一个问题。请尽可能检查。谢谢
  • 好的,我去看看。
  • @Greyfrog,请结帐聊天,我已经提到了一些建议。
  • 再次感谢您。我正在阅读您提供的链接。还有一件事我已经弄清楚了,在我与当前视图中的任何元素交互之前,CPU 使用率保持为零。一旦交互,CPU 使用率永远不会回到零,即使您不再与 UI 交互。因此,罪魁祸首不是媒体播放器。我尝试使用简单的搜索栏。当我滑动到视图时,CPU 使用率保持为零,但只要我调整搜索栏,即使我不再与它交互,CPU 使用率也会上升并保持上升。你能猜出可能是什么原因吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多