zoukankan      html  css  js  c++  java
  • Adroid学习之 从源码角度分析-禁止使用回退按钮方案

    有时候,不能让用户进行回退操作,如何处理?

    查看返回键触发了哪些方法。在打开程序后把这个方法禁止了。
    问题:程序在后台驻留,这样就会出现,其他时候也不能使用回退按钮。如何处理,在onpase()时方法失效。
    方案一:
    1 //重载onBackPressed
    2 @Override
    3 public void onBackPressed() {
    4         // TODO Auto-generated method stub
    5         //super.onBackPressed();
    6 }

    查看Adroid源码 onBackPressed ()源码:

    1     public void onBackPressed() {
    2         finish();
    3     }

    重写这个方法会不会有什么问题呢?他执行一个finish();方法对其本身应该没什么问题,那么调用出呢?

    下面是Activity中调用的两处:
    Adroid源码调用1:
     1     public boolean onKeyDown(int keyCode, KeyEvent event) {
     2     //当按钮等于KEYCODE_BACK时执行下面方法,KEYCODE_BACK这个就是返回键
     3         if (keyCode == KeyEvent.KEYCODE_BACK) {
     4            //检测版本号   ECLAIR 值为:public static final int ECLAIR = 5;
     5             if (getApplicationInfo().targetSdkVersion
     6                     >= Build.VERSION_CODES.ECLAIR) {
     7             //当大于5是执行
     8             /**startTracking()解释:调用onKeyUp()方法。
     9             Call this during Callback.onKeyDown to have the system track the key through its final up (possibly including a long press). Note that only one key can be tracked at a time -- if another key down event is received while a previous one is being tracked, tracking is stopped on the previous event.
    10             */
    11                 event.startTracking();
    12             } else {
    13                 onBackPressed();
    14             }
    15             return true;
    16         }
    17 }

    Adroid源码调用2:

     1     public boolean onKeyUp(int keyCode, KeyEvent event) {
     2         if (getApplicationInfo().targetSdkVersion
     3                 >= Build.VERSION_CODES.ECLAIR) {
     4             if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
     5                     && !event.isCanceled()) {
     6                 onBackPressed();
     7                 return true;
     8             }
     9         }
    10         return false;
    11     }

      到这里可以看出我们在onBackPressed()被调用处,都是在按下返回键的情况下,所以可以冲写onBackPressed方法,因为是被调用的,虽然不会出错,但是效率应该不高。

    要不我们重写onKeyDown方法这样可行,直接拦截。
    1  @Override 
    2     public boolean onKeyDown(int keyCode, KeyEvent event) { 
    3         if(keyCode==KeyEvent.KEYCODE_BACK) {
    4             Toast.makeText(getApplicationContext(), "back press", Toast.LENGTH_LONG).show();
    5              return false; // Disable back button.............. 
    6 }

    但是会如果在按钮处直接拦截,效果应该会高一些,这样就不会触发上面这两个方法了。

    于是乎我们继续向上寻找。
    细心的朋友可能发现onBackPressed()调用了finish()方法,所以干脆我们重写它吧。
    方案二:重载finish函数:
    查看Android的 finish()源码:
     1 public void finish() {
     2         if (mParent == null) {
     3             int resultCode;
     4             Intent resultData;
     5             synchronized (this) {
     6                 resultCode = mResultCode;
     7                 resultData = mResultData;
     8             }
     9             if (Config.LOGV) Log.v(TAG, "Finishing self: token=" + mToken);
    10             try {
    11                 if (ActivityManagerNative.getDefault()
    12                     .finishActivity(mToken, resultCode, resultData)) {
    13                     mFinished = true;
    14                 }
    15             } catch (RemoteException e) {
    16                 // Empty
    17             }
    18         } else {
    19             mParent.finishFromChild(this);
    20         }
    21     }

    查看Android源码中调用它的方法:

     1     /**
     2      * This is called when a child activity of this one calls its
     3      * {@link #finish} method. The default implementation simply calls
     4      * finish() on this activity (the parent), finishing the entire group.
     5      *
     6      * @param child The activity making the call.
     7      *
     8      * @see #finish
     9      */
    10     public void finishFromChild(Activity child) {
    11         finish();
    12     }

    从说明中我们知道这个方法是在子Activity结束时调用的这个方法,所以不行,如果我们要重写,需要进行判断拿到的键值。效率不高。

    继续寻找,看看哪里执行了调用方法按键吧。
    方案三:重写keyevent方法 大括号里加上return true 这样就禁用父类方法达到禁止返回键的目的 
    Android源码中找来找去找到了这个:
     1  /**
     2      * Called to process key events. You can override this to intercept all
     3      * key events before they are dispatched to the window. Be sure to call
     4      * this implementation for key events that should be handled normally.
     5      *
     6      * @param event The key event.
     7      *
     8      * @return boolean Return true if this event was consumed.
     9      */
    10     public boolean dispatchKeyEvent(KeyEvent event) {
    11         onUserInteraction();
    12         Window win = getWindow();
    13         if (win.superDispatchKeyEvent(event)) {
    14             return true;
    15         }
    16         View decor = mDecor;
    17         if (decor == null) decor = win.getDecorView();
    18         return event.dispatch(this, decor != null
    19                 ? decor.getKeyDispatcherState() : null, this);
    20     }

    就是在按钮触发的事件,当然是Activity中的。到此我们发现我们找到地方了,按钮进入后第一个处理的地方,再次我们重写这个方法就OK了。

     1 @Override
     2 
     3 public boolean dispatchKeyEvent(KeyEvent event) {
     4 
     5 if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) 
     6         {     
     7 
     8      return true; 
     9 
    10         }
    11 
    12 return super.dispatchKeyEvent(event);
    13 
    14 }

    一步一步行走,做好每一件事情。
  • 相关阅读:
    1、C#多线程基础理论
    ASP.NET MVC过滤器学习笔记
    C# 虚方法
    asp.net面试题总结1(未完待续。。。。)
    Linux高级调试与优化——进程管理和调度
    Linux高级调试与优化——内存管理
    Linux高级调试与优化——用户态堆
    Linux高级调试与优化——信号量机制与应用程序崩溃
    Linux高级调试与优化——gdb调试命令
    Nor Flash芯片特性分析
  • 原文地址:https://www.cnblogs.com/dava/p/3688577.html
Copyright © 2011-2022 走看看