美文网首页Android 经典笔记
Android 经典笔记之一

Android 经典笔记之一

作者: 杨充211 | 来源:发表于2017-08-08 21:12 被阅读42次

    Android 经典总结案例一
    目录介绍:
    1.完美解决onActivityResult提前执行调用的一系列问题
    1.1 出现的问题
    1.2 解决方案
    1.3 相关原理说明
    1.4 知识拓展
    2.EditText调用软键盘搜索的setOnKeyListener方法事件执行两次
    2.1 出现的问题
    2.2 解决方案
    2.3 相关原理说明
    2.4 知识拓展
    3.关于64k方法书限制的原理和解决方案探讨
    3.1 先看看报错
    3.2 64k****产生原因?
    3.3 如何解决64k的问题
    3.4 优化Multidex的开发和构建

    1.完美解决onActivityResult提前执行调用的一系列问题

    这是原本要启动的MainActivity
    int requestCode = 200;
    Intent intent = new Intent(this,SecondActivity.class);
    startActivityForResult(intent,requestCode);
    
    SecondActivity回传携带的数据
    Intent mIntent = new Intent();
    mIntent.putExtra("addr_id", retData.get(position));
    // 设置结果,并进行传送
    setResult(resultCode, mIntent);     
    finish()
    
    清单文件manifest.xml配置
    <activity android:name=".activity.SecondActivity" android:launchMode="singleTask"/>
    

    1.1.问题:代码没有任何问题,onActivityResult方法一直回调不过来数据,debug调试以后才发现onActivityResult方法在开启另外一个activity的时候提前执行了
    1.2.解决方案: 发现manifest.xml配置AddressActivity的启动模式是singleTask,就抱着试试看的态度,把他改成了标准启动模式,然后突然回传数据
    1.3.原理说明:
    如图:假设当前的应用程序存在两个栈:其中一个直接显示在屏幕上负责与用户完成交互,叫BackStack;另一个是隐藏在后台的background task,且位于该栈顶的Activity Y的启动模式被设置为singleTask。
    参考官方文档可知:

    Image.png

    在上图中,存在着前两个栈,其中直接显示在屏幕上与用户交互的Back Stack,及另一个隐藏在后台的Background Task,该栈栈顶的Activity Y其launchMode为singleTask。
    如果在Activity 2中调用BackgroundTask中已经启动过的Activity Y,则Background Task内占据屏幕并且该Task下所有的栈都会保留当前的栈位置及顺序push进Back Task形成新的结构,顺序由上至下为Activity Y→Activity X→Activity 2→Activity 1。
    在Activity Y界面按返回键,则ActivityY出栈,Activity X占据屏幕!注意,由Activity2调用的Activity Y,但返回键后,回退显示的是Activity X!所以即使在Activity Y执行setResult(),Activity 2也是无法接收到的。换回文章开头的问题,即在JumpActivity处启动LoginActivity(已经被设置singleTask了),则LoginActivity的setResult()结果有可能不会传给JumpActivity。
    继续按返回键,则才回到Activity 2。
    由于这种现象的存在,所以android系统处于某种保护机制,发现将要跳转的Activity的启动模式是singleTask时,若需要执行onActivityResult()函数则立即执行。这样就好理解多了。

    1.4.知识延伸:
    singleTop模式,可用来解决栈顶多个重复相同的Activity的问题。
    singleTask模式和后面的singleInstance模式都是只创建一个实例的。
    当intent到来,需要创建singleTask模式Activity的时候,系统会检查栈里面是否已经有该Activity的实例。如果有直接将intent发送给它。
    singleInstance模式解决了这个问题(绕了这么半天才说到正题)。让这个模式下的Activity单独在一个task栈中。这个栈只有一个Activity。导游应用和google地图应用发送的intent都由这个Activity接收和展示。

    2.EditText调用软键盘搜索的setOnKeyListener方法事件执行两次

    etProjectName.setOnKeyListener(new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_ENTER) {
            // 先隐藏键盘
            ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE))
                .hideSoftInputFromWindow(PublishProjectActivity.this.getCurrentFocus()
                    .getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
            //进行搜索操作的方法,在该方法中可以加入mEditSearchUser的非空判断
            **search();     //执行两次,想一想为什么?**
            return true;
        }
        return false;
        }
    });
    

    2.1.问题:点击后事件执行两次
    2.2.原理分析:
    setOnKeyListener之所以执行两次就是因为down和up占用了

    2.3.解决方案:
    第一种方案

    etProjectName.setOnKeyListener(new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
        **//发现执行了两次因为onkey事件包含了down和up事件,所以只需要加入其中一个即可。**
    **    //这个是个取巧的办法**
    **    if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_DOWN)** {
            // 先隐藏键盘
            ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE))
                .hideSoftInputFromWindow(PublishProjectActivity.this.getCurrentFocus()
                    .getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
            //进行搜索操作的方法,在该方法中可以加入mEditSearchUser的非空判断
            search();     //执行两次,想一想为什么?
            return true;
        }
        return false;
        }
    });
    

    第二种方案

    et.setOnEditorActionListener(new TextView.OnEditorActionListener() { 
        @Override 
        public boolean onEditorAction(TextView v, int actionId, KeyEvent event){ 
            //判断是否是“放大镜”键【简称搜索键】
            if(actionId == EditorInfo.IME_ACTION_SEARCH){ 
            //隐藏软键盘 
            //对应逻辑操作
            return true; 
            } 
            return false; 
        } 
    });
    

    需要注意的是 setOnEditorActionListener这个方法,并不是在我们点击EditText的时候触发,也不是在我们对EditText进行编辑时触发,而是在我们编辑完之后点击软键盘上的各种键才会触发

    2.4.知识延伸:
    修改Editview属性:Android:imeOptions="actionSearch" 在该Editview获得焦点的时候将“回车”键改为“搜索”

    android:singleLine="true"      不然回车【搜索】会换行
    可以随自己的需求更改软键盘右下角的显示样式,例如:搜索,下一步,Q(搜索图标)
    
    actionNone : 按下后光标到下一行(回车)
    actionGo : 按下后搜索(Go)
    actionSearch : 放大镜【搜索】
    actionSend : Send 按下后发送
    actionNext : Next 下一步
    actionDone : Done,确定/完成,隐藏软键盘(包括不是最后一个文本输入框的情况也会隐藏)
    使用方法:在xml里面写布局时直接加给EditTxt的imeOptions属性,例如:
    
    项目开发中涉及到按键事件处理:
    
    **“dispatchKeyEvent” “onKeyDown ”“onKeyLisenter” 简单理解**
    接受按键优先级:
    
    **dispatchKeyEvent > Activity的onKeyDown > view的onKeyLisenter**
    其中按键处理事件return true ;表示已消耗此事件,不再继续传递;
    

    3.关于64k方法书限制的原理和解决方案探讨
    3.1 先看看报错,截图如下

    [图片上传中。。。(2)]
    3.2 产生原因?
    Android APK文件本质上是一个压缩文件,它包含的classes.dex文件是Dalvik字节码文件,这个dex文件中存放的就是编译后的Java代码。Dalvik可执行文件规范限制了单个.dex文件最多引用的方法数是65536个。Android官方的叫法是64k,也就是1024x64=65536个Java方法。
    其中包含第三方库,App应用,以及Framework及自身的方法。
    3.3 如何解决64k的问题
    google为了规避上述问题,推出了MultiDex解决方案解决方法数超限问题。
    A:首先需要配置build.gradle文件【注意是项目下的build文件】
    添加代码如下所示:

    android {
        compileSdkVersion 21
        buildToolsVersion "21.1.0"    //必须使用21或之后的版本
        defaultConfig {
            minSdkVersion 14
            targetSdkVersion 21       
    
            // Enabling multidex support.
            **multiDexEnabled true**
        }
    }
    
    dependencies {
        compile 'com.android.support:multidex:1.0.0'
    }
    

    B:配置Application
    如果用户没有重写Application,只需修改Manifest文件中的内容:

    <application
        android:name="android.support.multidex.MultiDexApplication">
    </application>
    

    如果用户继承变重写了Application,可以将继承的Application换成MultiDexApplication。 或者重写attachBaseContext() 方法

    @Override
     protected void attachBaseContext(Context base) {
         super.attachBaseContext(base);
         MultiDex.install(this);     //这个方法是在onCreate之前执行的
    }
    

    特别注意,如果没有实现这部分代码,运行时会出现NoClassDefFoundError的错误,尤其是在依赖三方函数库时。

    3.4 优化Multidex的开发和构建

    这块看书后还是不太懂,

    后续:
    平时喜欢写写文章,笔记。别人建议我把笔记,以前写的东西整理,然后写成博客,所以我会陆续整理文章,只发自己写的东西,敬请期待:
    知乎:https://www.zhihu.com/people/yang-chong-69-24/pins/posts
    领英:https://www.linkedin.com/in/chong-yang-049216146/
    简书:http://www.jianshu.com/u/b7b2c6ed9284
    csdn:http://my.csdn.net/m0_37700275
    网易博客:http://yangchong211.blog.163.com/
    新浪博客:http://blog.sina.com.cn/786041010yc
    github:https://github.com/yangchong211
    喜马拉雅听书:http://www.ximalaya.com/zhubo/71989305/
    脉脉:yc930211
    开源中国:https://my.oschina.net/zbj1618/blog

    相关文章

      网友评论

        本文标题:Android 经典笔记之一

        本文链接:https://www.haomeiwen.com/subject/eqyxrxtx.html