Android开发经验谈Android开发Android技术知识

Android:双击返回键退出应用

2019-07-18  本文已影响203人  彭旭锐

前言


1. 需求分析

对比分析市面上App,可以分为四类,归纳出完整流程图:

  1. Facebook、Instagram等:主Activity -> 主Tab -> 桌面

  2. 爱奇艺、高德地图、招商等(最多):主Activity -> 两次点击 -> 结束Activity

  3. 微信、支付宝等:主Activity -> 返回桌面

  4. QQ音乐等:主Activity -> 两次点击 -> 返回桌面

流程图

2. 最小可行方案

class MainActivity : AppCompatActivity() {
    /**
     * 上次点击返回键的时间
     */
     private var lastBackPressTime = -1L
     ...
     override fun onBackPressed() {
        val currentTIme = System.currentTimeMillis()
        if(lastBackPressTime == -1L || currentTIme - lastBackPressTime >= 2000){
            // 显示提示信息
            showBackPressTip()
            // 记录时间
            lastBackPressTime = currentTIme
        }else{
            //退出应用
            finish()
        }
    }
    private fun showBackPressTip(){
        Toast.makeText(this,"再按一次退出",Toast.LENGTH_SHORT).show();
    }
}

更多介绍参考:Android: Key事件分发机制

更多介绍参考:Android: 任务栈与Activity启动模式


3. 源码分析

由Key事件分发机制可知,如果没有其他View消费了返回键事件,最终将分发给Activity#onKeyUp():

// android.app.Activity:
public boolean onKeyUp(int keyCode, KeyEvent event) {
    if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.ECLAIR) {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
                && !event.isCanceled()) {
            // 返回键事件
            onBackPressed();
            // 消费KeyEvent.KEYCODE_BACK事件
            return true;
        }
     }
     // 不消费
     return false;
 }
// android.app.Activity:
public void onBackPressed() {
    // 收起可折叠ActionBar
    if (mActionBar != null && mActionBar.collapseActionView()) {
        return;
    }
​
    // 弹出Fragment回退栈栈顶的Fragment
    FragmentManager fragmentManager = mFragments.getFragmentManager();
    if (fragmentManager.isStateSaved() 
            || !fragmentManager.popBackStackImmediate()) {
        finishAfterTransition();
    }
 }

4. 演进

// android.app.Activity:
override fun onBackPressed() {
    // 弹出support库Fragment回退栈
    if(popSupportBackStack()){
        return;
    }
    val currentTIme = System.currentTimeMillis();
    ...
}
/**
 * @return true:没有Fragment弹出 false:有Fragment弹出
 */
private fun popSupportBackStack():Boolean{
    // 当Fragment状态保存了
    return supportFragmentManager.isStateSaved 
          ||supportFragmentManager.popBackStackImmediate()
}

更多介绍参考:Android: Activity状态管理

// android.app.Activity:
override fun finishAfterTransition() {
    if(popSupportBackStack()){
        return
    }
    val currentTIme = System.currentTimeMillis();
    if(lastBackPressTime == -1L || currentTIme - lastBackPressTime >= 2000){
        showBackPressTip()
        lastBackPressTime = currentTIme
    }else{
        //退出应用
        finish()
    }
}
class WebViewImpl(context: Context) : WebView(context) {
    override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
        // 判断可以向上导航
        if(canGoBack()){
            // 导航到之前的页面
            goBack()
            return true
        }
        return false
    }
}

5. 延伸阅读


感谢喜欢!你的点赞是对我最大的鼓励!

上一篇下一篇

猜你喜欢

热点阅读